2013-08-01 2 views
2

현재 PHP에 로그인하여 CAS 단일 로그인 서버로 인증하려고 노력하고 있습니다.PHP를 사용하여 CAS 인증에 어려움을 겪고 있습니다.

공식 사이트는 인증을 처리하고 사용자를 로그인하는 것으로 간주되는 일부 기본 source code here을 가지고 있습니다. 내가 볼 수있는 한, 테스트 과정에서 1 단계와 2 단계가 완료됩니다 (기본 프로세스는 see this diagram). 테스트 서버에 로그인하면 3 단계를 완료하고 나를 내 페이지로 보낸 URL에서 서비스 티켓을 검색 할 수 있습니다. 프로세스의 4 단계와 5 단계를 완료 할 수있는 예제가없는 것 같습니다. 그것을하기 위해 자신의 코드를 작성해야하는 것이 맞습니까?

나는 티켓을 되찾고 cURL 또는 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); 
    } 
} 

내가 직접 예를 들어 브라우저를 통해 액세스하는 경우 I는 서비스에서 합법적 인 응답을 얻을 수 있습니다

는 Active Directory의 사용자 ID가 포함 된 XML 응답 반환
https://server.com/cas/serviceValidate?service=http%3A%2F%2Flocalhost%3A8080%2Ftestcas%2Fcas-client.php&ticket=ST-35717-XLiWQ2ucCCuks2wsVNMJ-cas 

:

<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>"; 
관련 문제