2013-04-15 56 views
4

我有一個nginx網絡服務器,使用php-fpm執行腳本,我想獲取瀏覽服務器的客戶端的NTLMv2憑證。我的本地網絡中有一臺代理服務器來驗證用戶身份。問題是,如何使nginx服務器進行身份驗證,或者PHP使用NTLMv2獲取我的用戶的憑據並將回傳信息傳給我?我顯然至少需要知道他們的用戶名,以確保客戶端在系統中獲得正確的憑據。使用NTLMv2的PHP單點登錄

我很好地做了一個上游連接到代理服務器時,例如我去/login.php,只要它傳遞有關客戶端的信息返回到服務器關於客戶端,例如用戶名字在Type-3消息中找到,我可以將這些信息保存在他們的會話中,並從這一點開始使用它。


我有一臺Linux服務器在局域網內運行nginx,PHP和SQLite。連接到此服務器的計算機都是使用Windows登錄到網絡的Windows。登錄使用NTLMv2身份驗證,並通過代理訪問網絡外的網站,所有客戶端都必須通過該代理連接到外部網絡。我想要做的是使用NTLMv2身份驗證信息登錄到LAN Web服務器。有關我如何做到這一點的任何建議?

+1

哇,做一個谷歌搜索「nginx NTLMv2」已經在頭版,我只問了7分鐘前這個問題。 –

回答

5

我認爲最簡單的方法就是在nginx服務器上模擬NTLMv2身份驗證,將請求重定向到代理並檢查答案。 我無法重現您的設置,因此下面的代碼沒有經過測試,但它應該可以工作,或者它應該給您一些幫助。

<?php 
$headers = getallheaders() //Equivalent to apache_request_headers() to get the headers of the request. 

if(!isset($headers['Authorization'])) //Check Authorization Header 
{ 
    header('HTTP/1.1 401 Unauthorized'); //Return Unauthorized Http-Header (NTLM protocol) 
    header('WWW-Authenticate: NTLM'); //Authenticcation Information (NTLM protocol) 
} 
else 
{ 
    if(substr($headers['Authorization'],0,4) == 'NTLM') //Check whether Authorization Header is valid 
    { 
     $message = base64_decode(substr($headers['Authorization'], 5)) //Get NTLM Message from Authrization header 
     if(substr($message, 0, 8) == "NTLMSSP\x00") //Check whether NTLM Message is valid 
     { 
      if($message[8] == "\x01") //Check whether it's type-1-NTLM Message 
      { 
       //$message holds the base64 encoded type-1-NTLM message 
       $ch = curl_init(); //Use cURL to connect to web via proxy 
       curl_setopt($ch, CURLOPT_URL, "http://www.google.com"); 
       curl_setopt($ch, CURLOPT_HTTPHEADER, array('Authorization: '.$headers['Authorization'])); 
       curl_setopt($ch, CURLOPT_PROXY, <Your Proxy Adress>); 
       curl_setopt($ch, CURLOPT_PROXYPORT, <Your Proxy Port>); 
       curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); 
       $result = curl_exec($ch); 
       $info = curl_getinfo($ch); 
       curl_close($ch); 
       $header = substr($result, 0, $info['header_size']); 
       $body = substr($result, $info['header_size'], $info['download_content_length']-$info['header_size']); 
       $c_headers = explode("\r\n", $header); 
       for($i = 0; $i < (count($c_headers) - 2); $i++) 
       { 
        header($c_headers[$i]); 
        if(substr($c_headers[$i], 0, 16) == "WWW-Authenticate") 
        { 
         //Thats your type-2-message header Format: WWW-Authenticate: NTLM <base64-type-2-message> 
        } 
       } 
      } 
      else if ($message[8] == "\x03") //Check whether it's type-3-NTLM Message 
      { 
       $ch = curl_init(); //Use cURL to connect to web via proxy 
       curl_setopt($ch, CURLOPT_URL, "http://www.google.com"); 
       curl_setopt($ch, CURLOPT_HTTPHEADER, array('Authorization: '.$headers['Authorization'])); 
       curl_setopt($ch, CURLOPT_PROXY, <Your Proxy Adress>); 
       curl_setopt($ch, CURLOPT_PROXYPORT, <Your Proxy Port>); 
       $result = curl_exec($ch); 
       $info = curl_getinfo($ch); 
       curl_close($ch); 
       if($info['CURLINFO_HTTP_CODE'] == 200) 
       { 
        //Authenticated 
        //$msg holds the base64 encoded type-3-NTLM message (which includes username, domain, workstation) 
       } 
      } 
     } 
    } 
}?> 

我使用NTLM協議的這一參考:http://davenport.sourceforge.net/ntlm.html

我希望這會幫助你。隨意發表評論。

+0

感謝您的幫助,稍後我會試用您的代碼! –

+0

在類型1的塊中,'$ response'永遠不會在任何地方設置,但會被使用。所以我設置了'curl_setopt($ ch,CURLOPT_RETURNTRANSFER,1);'並將每個'$ response'改爲'$ result'。雖然,目前效果並不理想...... –

+0

@MarkTomlin對不起,我的錯。您是否嘗試將e_reporting設置爲E_ALL?也許你可以使用Method syslog()在你的日誌上打印一些調試信息,比如$ message或$ result。 – Max