2013-08-01 57 views
2

我目前正試圖讓PHP登錄並通過CAS單點登錄進行身份驗證,這在證明是困難的服務器上。使用PHP進行CAS認證的困難

官方網站上有這應該處理身份驗證和登錄用戶的一些基本source code here。據我所知,在我的測試中,它完成了流程中的步驟1和步驟2(基本流程爲see this diagram)。一旦我登錄到測試服務器,我就可以完成第3步,並從將URL發回我的頁面的URL中檢索服務票證。似乎沒有任何地方可以完成該流程的第4步和第5步。我需要編寫自己的代碼來做到這一點是否正確?

我試圖買票回來,然後用我自己的一些代碼捲曲或沒有運氣的fsockopen把它送上驗證服務。

if (isset($_GET['ticket'])) 
{ 
    $currentProtocol = (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] != 'off') ? 'https://' : 'http://'; 
    $requestUri = explode('?', $_SERVER['REQUEST_URI']); 
    $requestUri = $requestUri[0]; 
    $ticket = $_GET['ticket']; 
    $port = ($_SERVER['SERVER_PORT'] != 80) ? ':8080' : ''; 
    $currentUrl = urlencode($currentProtocol . $_SERVER['SERVER_NAME'] . $port . $requestUri); 
    $validateUrl = 'ssl://server.com/cas/serviceValidate?service=' . $currentUrl . '&ticket=' . $ticket; 

    $errno = 0; 
    $errstr = ''; 
    $fp = fsockopen($validateUrl, 443, $errno, $errstr, 30); 

    if (!$fp) { 
     echo "$errstr ($errno)<br />\n"; 
    } 
    else { 
     var_dump($fp); 

     $out = "GET/HTTP/1.1\r\n"; 
     $out .= "Host: www.example.com\r\n"; 
     $out .= "Connection: Close\r\n\r\n"; 
     fwrite($fp, $out); 
     while (!feof($fp)) { 
      echo fgets($fp, 128); 
     } 
     fclose($fp); 
    } 
} 

我可以從服務的合理反應,如果我直接例如訪問它通過瀏覽器:

https://server.com/cas/serviceValidate?service=http%3A%2F%2Flocalhost%3A8080%2Ftestcas%2Fcas-client.php&ticket=ST-35717-XLiWQ2ucCCuks2wsVNMJ-cas 

返回包含活動目錄用戶ID的XML響應:

<cas:serviceResponse xmlns:cas='http://www.server.com/cas'> 
    <cas:authenticationSuccess> 
     <cas:user>c314317</cas:user> 
    </cas:authenticationSuccess> 
</cas:serviceResponse> 

但我真的認爲我需要能夠直接從服務器端使用PHP訪問該URL,然後一旦我擁有用戶ID,我就可以將其與我們的系統連接起來並將它們登錄到網站中。

我的問題是,似乎沒有被任何代碼來處理事物的票和驗證方。任何人都可以將我指向正確的方向嗎?

非常感謝。

回答

0

好吧我想我用cURL解決了這個問題。我沒有將CURLOPT_SSL_VERIFYPEER設置爲false,這就是它失敗的原因。現在我可以使用PHP獲得XML響應,處理XML響應並檢索用戶ID。下面的代碼:

// Get the current server address we are executing the PHP from 
$currentProtocol = (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] != 'off') ? 'https://' : 'http://'; 
$requestUri = explode('?', $_SERVER['REQUEST_URI']); 
$requestUri = $requestUri[0]; 
$ticket = $_GET['ticket']; 
$port = ($_SERVER['SERVER_PORT'] != 80) ? ':' . $_SERVER['SERVER_PORT'] : ''; # Don't need the port if it's 80, but needed if for example test server is running port 8080 
$currentUrl = $currentProtocol . $_SERVER['SERVER_NAME'] . $port . $requestUri; 

// Setup the validation URL 
$validateUrl = 'https://sso.server.com/cas/serviceValidate?service=' . strtolower(urlencode($currentUrl)) . '&ticket=' . $ticket; 

// Send request to validate the URL 
$ch = curl_init(); 
curl_setopt($ch, CURLOPT_URL, $validateUrl);  # The URL to get the data from 
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);  # Return the value of curl_exec() instead of outputting it out directly. 
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 120);  # The number of seconds to wait while trying to connect 
curl_setopt($ch, CURLOPT_TIMEOUT, 120);    # The maximum number of seconds to allow cURL functions to execute 
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);  # Check the existence of a common name and also verify that it matches the hostname provided 
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); # Stop cURL from verifying the peer's certificate 
curl_setopt($ch, CURLOPT_HEADER, false);   # Don't include the header in the output 

// Execute the request and close the handle 
$xml = curl_exec($ch); 
curl_close($ch); 

// Get the user ID from the XML using XPath 
$xml = new SimpleXMLElement($xml); 
$result = $xml->xpath('cas:authenticationSuccess/cas:user'); 
$userId = null; 

while(list(, $node) = each($result)) 
{ 
    $userId = (string) $node; 
} 

echo 'user: ' . $userId . "<br>";