我正在开发单点登录 (SSO) PHP 应用程序。
用户登录他们的 Windows session ,并且他们希望使用他们的 Windows 帐户(与 LDAP Active Directory 连接)自动登录应用程序。
我试过这个脚本:
<?php
$headers = apache_request_headers(); // Récupération des l'entêtes client
if (@$_SERVER['HTTP_VIA'] != NULL){ // nous verifions si un proxy est utilisé : parceque l'identification par ntlm ne peut pas passer par un proxy
echo "Proxy bypass!";
} elseif(!isset($headers['Authorization'])) { //si l'entete autorisation est inexistante
header( "HTTP/1.0 401 Unauthorized" ); //envoi au client le mode d'identification
header( "WWW-Authenticate: NTLM" ); //dans notre cas le NTLM
exit; //on quitte
}
if(isset($headers['Authorization'])) //dans le cas d'une authorisation (identification)
{
if(substr($headers['Authorization'],0,5) == 'NTLM '){ // on vérifit que le client soit en NTLM
$chaine=$headers['Authorization'];
$chaine=substr($chaine, 5); // recuperation du base64-encoded type1 message
$chained64=base64_decode($chaine); // decodage base64 dans $chained64
if(ord($chained64{8}) == 1){
// |_ byte signifiant l'etape du processus d'identification (etape 3)
// verification du drapeau NTLM "0xb2" à l'offset 13 dans le message type-1-message (comp ie 5.5+) :
if (ord($chained64[13]) != 178){
echo "NTLM Flag error!";
exit;
}
$retAuth = "NTLMSSP".chr(000).chr(002).chr(000).chr(000).chr(000).chr(000).chr(000).chr(000);
$retAuth .= chr(000).chr(040).chr(000).chr(000).chr(000).chr(001).chr(130).chr(000).chr(000);
$retAuth .= chr(000).chr(002).chr(002).chr(002).chr(000).chr(000).chr(000).chr(000).chr(000);
$retAuth .= chr(000).chr(000).chr(000).chr(000).chr(000).chr(000).chr(000);
$retAuth64 =base64_encode($retAuth); // encode en base64
$retAuth64 = trim($retAuth64); // enleve les espaces de debut et de fin
header( "HTTP/1.0 401 Unauthorized" ); // envoi le nouveau header
header( "WWW-Authenticate: NTLM $retAuth64" ); // avec l'identification supplémentaire
exit;
} else if(ord($chained64{8}) == 3) {
// |_ byte signifiant l'etape du processus d'identification (etape 5)
// on recupere le domaine
$lenght_domain = (ord($chained64[31])*256 + ord($chained64[30])); // longueur du domain
$offset_domain = (ord($chained64[33])*256 + ord($chained64[32])); // position du domain.
$domain = str_replace("\0","",substr($chained64, $offset_domain, $lenght_domain)); // decoupage du du domain
//le login
$lenght_login = (ord($chained64[39])*256 + ord($chained64[38])); // longueur du login.
$offset_login = (ord($chained64[41])*256 + ord($chained64[40])); // position du login.
$login = str_replace("\0","",substr($chained64, $offset_login, $lenght_login)); // decoupage du login
$lenght_host = (ord($chained64[47])*256 + ord($chained64[46]));
$offset_host = (ord($chained64[49])*256 + ord($chained64[48]));
$host = str_replace("\0","",substr($chained64, $offset_host, $lenght_host));
if ( $login != NULL){
echo $login;
} else {
echo "NT Login empty!";
}
}
}
}
?>
此脚本正在处理此配置:
但是现在我需要在这个配置上实现它并且它不起作用:
由于这种情况,我不断收到“NTLM 标志错误!”的消息:
if (ord($chained64[13]) != 178){
echo "NTLM Flag error!";
exit;
}
我试过 :
if (ord($chained64[13]) != 130){
因为 ord($chained64[13]) 返回 130,但我不能进入这种情况:
} else if(ord($chained64{8}) == 3) {
$lenght_domain = (ord($chained64[31])*256 + ord($chained64[30])); // longueur du domain
$offset_domain = (ord($chained64[33])*256 + ord($chained64[32])); // position du domain.
$domain = str_replace("\0","",substr($chained64, $offset_domain, $lenght_domain)); // decoupage du du domain
//le login
$lenght_login = (ord($chained64[39])*256 + ord($chained64[38])); // longueur du login.
$offset_login = (ord($chained64[41])*256 + ord($chained64[40])); // position du login.
$login = str_replace("\0","",substr($chained64, $offset_login, $lenght_login)); // decoupage du login
$lenght_host = (ord($chained64[47])*256 + ord($chained64[46]));
$offset_host = (ord($chained64[49])*256 + ord($chained64[48]));
$host = str_replace("\0","",substr($chained64, $offset_host, $lenght_host));
if ( $login != NULL){
echo $login;
} else {
echo "NT Login empty!";
}
}
因为
ord($chained64{8})
总是返回 1。编辑 2015-05-11 :
echo exec('whoami');
-> 当我在 cmd.exe 中执行这个命令时,我得到了当前登录的用户,但是当我在 PHP 中执行它时,我得到了 nt_authority/system。 echo exec('whoami');
时, 我只得到用于 Apache 的登录名,而不是当前用户。 _PATH_
是我的 php 文件的路径,也许这是错误的?):<Directory "E:/_PATH_">
Options None
AllowOverride All
Order allow,deny
Allow from all
AuthName "SSPI Protected Place"
AuthType SSPI
SSPIAuth On
SSPIAuthoritative On
SSPIOfferBasic On
SSPIOmitDomain On
Require valid-user
</Directory>
编辑 2015-05-12 :
编辑 2015-05-13 :
编辑 2015-05-18 :
根据@timclutton 在他的回答中所说,将我的 httpd.conf 更改为与 Apache 2.4 兼容:
<Directory "E:/_PATH_">
Require all denied
AllowOverride All
Options None
AuthName "SSPI Authentication"
AuthType SSPI
SSPIAuth On
SSPIAuthoritative On
SSPIOmitDomain On
Require valid-user
Require user "NT AUTHORITY\ANONYMOUS LOGON" denied
</Directory>
编辑 2015-05-19 :
AuthType 基本
AuthName "需要身份验证"
AuthUserFile "E:/PATH/.htpasswd"
需要有效用户
命令允许,拒绝
所有人都允许
最佳答案
When I try with Firefox, I get a prompt for a login and a password. When I post the prompt, the script gets the login from the prompt, but this is not what I want to do : I have to get this to work with IE, and I don't want to type again login and password. I want the login of the current Windows session.
您可以通过更改 Firefox 设置来删除提示:
对于 IE,您需要将页面(内联网)的安全设置设置为低于 Internet 其余部分的安全设置。
请查看 https://superuser.com/questions/148063/why-does-internet-explorer-keep-asking-me-for-ntlm-credentials-in-an-intranet-zo
关于php - NTLM 身份验证 - 在 PHP 中获取 Windows 登录名、域和主机,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30070058/