NTLM验证 - 获取在PHP中的Windows登录,域名和主机 [英] NTLM Authentication - Get Windows login, domain and host in PHP

查看:2050
本文介绍了NTLM验证 - 获取在PHP中的Windows登录,域名和主机的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我工作的一个单点登录(SSO)的PHP应用程序。

 用户登录他们的Windows会话,他们希望在他们的Windows帐户(与LDAP的Active Directory连接)应用程序来自动登录。

我试过这个脚本:

 < PHP
$头= apache_request_headers(); //调理宫L'entêtes客户端如果(@ $ _ SERVER ['HTTP_VIA']!= NULL){//理性verifions SI联合国代理ESTutilisé:parceque L'识别票面NTLM东北peut考绩合格者标准杆未代理
    回声代理绕行!
} ELSEIF(!使用isset($头['授权'])){// SI L'entete autorisation EST inexistante
    标题(HTTP / 1.0 401未经授权); // envoi太子港客户端文件模式D'鉴定
    标题(WWW验证:NTLM); //丹斯巴黎CAS乐NTLM
    出口; //对quitte}如果(使用isset($头['授权']))//丹斯乐德中科院UNE授权(识别)
{
    如果(SUBSTR($头['授权'],0,5)=='NTLM'){//在vérifit阙乐客户端搜易得恩NTLM        $ CHAIN​​E = $标题['授权'];
        $ CHAIN​​E = SUBSTR($ CHAIN​​E,5); //休养杜的base64恩codeD TYPE1消息
        $ chained64 = base64_de code($ CHAIN​​E); // decodage的base64丹斯$ chained64        如果(ORD($ chained64 {8})== 1){
        // | _字节signifiant L'Etape酒店杜突D'识别(Etape酒店3)        //验证杜德拉普NTLM0xb2A L'偏移13丹斯乐消息类型1消息(补偿5.5及更高版本):
            如果(ORD($ chained64 [13])!= 178){
                回声NTLM标志错误!;
                出口;
            }            $ 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_en code($ retAuth); // EN code连接的base64
            $ retAuth64 =修剪($ retAuth64); // enleve莱ESPACES日亮相和de鳍
            标题(HTTP / 1.0 401未经授权); // envoi乐暴发户头
            标题(WWW验证:NTLM $ retAuth64); // AVEC L'识别supplémentaire
            出口;        }否则如果(ORD($ chained64 {8})== 3){
        // | _字节signifiant L'Etape酒店杜突D'识别(Etape酒店5)            //对recupere乐酒庄
            $ lenght_domain =(ORD($ chained64 [31])* 256 + ORD($ chained64 [30])); // longueur杜域
            $ offset_domain =(ORD($ chained64 [33])* 256 + ORD($ chained64 [32])); //位置杜域。
            $域= str_replace函数(\\ 0,,SUBSTR($ chained64,$ offset_domain,$ lenght_domain)); //剪纸嘟嘟域            //乐登录
            $ lenght_login =(ORD($ chained64 [39])* 256 + ORD($ chained64 [38])); // longueur杜登录。
            $ offset_login =(ORD($ chained64 [41])* 256 + ORD($ chained64 [40])); //位置都登录。
            $登录= str_replace函数(\\ 0,,SUBSTR($ chained64,$ offset_login,$ lenght_login)); //剪纸杜登录            $ lenght_host =(ORD($ chained64 [47])* 256 +的ord($ chained64 [46]));
            $ offset_host =(ORD($ chained64 [49])* 256 + ORD($ chained64 [48]));
            $主机= str_replace函数(\\ 0,,SUBSTR($ chained64,$ offset_host,$ lenght_host));
            如果($登录!= NULL){
                回声$登录;
            }其他{
                回声NT登录空!;
            }
        }
    }
}
?>

本脚本正在此配置:


  • Windows Server 2003中

  • 的Apache 2.2模块mod_auth_sspi

但现在我需要执行此此配置和它不工作:


  • 在Windows Server 2008

  • 的Apache模块与mod_authnz_sspi
  • 2.4.6

我不断收到NTLM标志错误!,因为这种情况:

 如果(ORD($ chained64 [13])!= 178){
    回声NTLM标志错误!;
    出口;
}

我试过:

 如果(ORD($ chained64 [13])!= 130){

由于ORD($ chained64 [13])将返回130,但我不能在这种情况下进入:

 }否则如果(ORD($ chained64 {8})== 3){
    $ lenght_domain =(ORD($ chained64 [31])* 256 + ORD($ chained64 [30])); // longueur杜域
    $ offset_domain =(ORD($ chained64 [33])* 256 + ORD($ chained64 [32])); //位置杜域。
    $域= str_replace函数(\\ 0,,SUBSTR($ chained64,$ offset_domain,$ lenght_domain)); //剪纸嘟嘟域    //乐登录
    $ lenght_login =(ORD($ chained64 [39])* 256 + ORD($ chained64 [38])); // longueur杜登录。
    $ offset_login =(ORD($ chained64 [41])* 256 + ORD($ chained64 [40])); //位置都登录。
    $登录= str_replace函数(\\ 0,,SUBSTR($ chained64,$ offset_login,$ lenght_login)); //剪纸杜登录    $ lenght_host =(ORD($ chained64 [47])* 256 +的ord($ chained64 [46]));
    $ offset_host =(ORD($ chained64 [49])* 256 + ORD($ chained64 [48]));
    $主机= str_replace函数(\\ 0,,SUBSTR($ chained64,$ offset_host,$ lenght_host));
    如果($登录!= NULL){
        回声$登录;
    }其他{
        回声NT登录空!;
    }
}

由于 ORD($ chained64 {8})总是返回1。


编辑2015年5月11日:


  • 我试图在PHP执行'WHOAMI命令,就像这样:回声EXEC('WHOAMI'); - >当我在cmd中执行此命令.exe文件,我得到的当前登录的用户,但是当我在PHP中执行它,我得到NT_AUTHORITY /系统。


  • 我假定PHP执行'WHOAMI命令时,Windows将检查Apache服务的登录。我走进Apache的属性,在登录选项卡,登录为Active Directory中的有效用户。但是,当PHP执行时回声EXEC('WHOAMI'); ,我只得到用于Apache的登录,而不是当前用户


  • 我使用的Internet Explorer 8的执行PHP脚本。


  • 我有这个在我的Apache httpd.conf( _PATH _ 是路径,我的PHP文件,也许这是错的?)

    <目录E:/ _ PATH _>
    选择无
    所有的AllowOverride
    为了允许,拒绝
    所有允许
    AuthName指令SSPI保护的地方
    AuthType选项SSPI
    SSPIAuth在
    SSPIAuthoritative在
    SSPIOfferBasic在
    SSPIOmitDomain在
    需要有效的用户
    < /目录>



编辑2015年5月12日:


  • 我登录的机器上的域用户


  • 当我尝试用Firefox,我得到一个提示登录名和密码。当我发布提示,该脚本会从提示登录,但是这不是我想做的事:我一定要得到这个在IE工作,我不想再次输入登录名和密码。我想当前的Windows会话的登录。


  • 在Firefox中,我走进了一下:config来network.automatic-NTLM的auth.trusted-URI的设置为我的域名,感谢@ThaDafinser。现在我不Firefox中得到提示了,一切工作,但我总是需要使它在IE浏览器。


  • 在IE浏览器,我设置本地Intranet安全到最低,但没有改变。


  • 在IE中,使用当前用户名和密码自动登录被选中为本地Intranet和放大器;受信任的站点。


  • 当我迫使IE问凭据的提示,如果我发布提示,IE不返回的凭据,相反,Firefox浏览器。



编辑2015年5月13日:


  • 我添加的URL,在IE浏览器信任的网站,什么都没有改变。


  • 我设置安全性低受信任的站点,什么都没有改变。


  • 我在IE> Internet选项>高级取消选中通过代理连接使用HTTP 1.1,我现在还不能对Internet Explorer会话信息,即使我使用提示。


  • 我添加了完整的URL在Internet Explorer> Internet选项>安全>本地Intranet>站点>高级


  • 在Internet Explorer> Internet选项>安全>本地Intranet>站点>高级,我还添加了比我在Firefox中添加,使其工作域(mycompany.com)相同的部分,但这并没有帮助。


编辑2015年5月18日:

改变我的httpd.conf是与Apache 2.4兼容的,根据是什么@timclutton在他回答说:

 <目录E:/ _ PATH _>
    要求所有被拒绝
    所有的AllowOverride
    选择无    AuthName指令SSPI认证
    AuthType选项SSPI
    SSPIAuth在
    SSPIAuthoritative在
    SSPIOmitDomain在
    需要有效的用户
    需要用户NT AUTHORITY \\ ANONYMOUS登录否认
< /目录>

编辑2015年5月19日:


  • 我试图设置SSPI的基本身份验证这一翻译,这是行不通的。


      AuthType选项基本
      AuthName指令需要身份验证
      的AuthUserFileE:/的 PATH 的/ htpasswd的
      需要有效的用户

    令允许,拒绝
      所有允许



解决方案

  

当我尝试用Firefox,我得到一个提示登录名和密码。当我发布提示,该脚本会从提示登录,但是这不是我想做的事:我一定要得到这个在IE工作,我不想再次输入登录名和密码。我想当前的Windows会话的登录。


您可以删除的提示,通过改变Firefox的设置:


  • 类型:关于:配置在地址栏

  • 检查network.automatic-NTLM的auth.trusted - URI的

  • 的值设置为您的域名,或域例如mycompany.com(单独用逗号多个值)的一部分

有关IE浏览器,你需要为你的页面(内部网)比互联网的其他设置较低的安全设置。
请参阅<一个href=\"http://superuser.com/questions/148063/why-does-internet-explorer-keep-asking-me-for-ntlm-credentials-in-an-intranet-zo\">http://superuser.com/questions/148063/why-does-internet-explorer-keep-asking-me-for-ntlm-credentials-in-an-intranet-zo

I am working on a Single Sign-On (SSO) PHP application.
Users log in their Windows session, and they want to be automatically logged in the application with their Windows account (connected with LDAP Active Directory).

I tried this script :

<?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!";
            }
        }
    }
}
?>

This script is working on this configuration :

  • Windows server 2003
  • Apache 2.2 with module mod_auth_sspi

But now I need to implement this on this configuration and it does not work :

  • Windows server 2008
  • Apache 2.4.6 with module mod_authnz_sspi

I keep getting "NTLM Flag error!", because of this condition :

if (ord($chained64[13]) != 178){
    echo "NTLM Flag error!";
    exit;
}

I tried :

if (ord($chained64[13]) != 130){

because ord($chained64[13]) returns 130, but I can not go in this condition :

} 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!";
    }
}

Because ord($chained64{8}) always returns 1.


Edit 2015-05-11 :

  • I tried executing the 'whoami' command in php, like this : echo exec('whoami'); -> when I execute this command in cmd.exe, I get the current logged user, but when I execute it in PHP, I get nt_authority/system.

  • I supposed that when PHP executes the 'whoami' command, Windows checks the login of Apache service. I went into Apache properties, in the 'Log On' tab, to log on as a valid user of the Active Directory. But then, when PHP executes echo exec('whoami');, I only get the login used for Apache, and not the current user.

  • I am using Internet Explorer 8 to execute the PHP script.

  • I have this in my Apache httpd.conf (_PATH_ is the path to my php files, maybe this is wrong ?) :

    <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>


Edit 2015-05-12 :

  • I am logged as a domain user on the machine

  • 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.

  • In Firefox, I went into about:config to set network.automatic-ntlm-auth.trusted-uris to my domain, thanks to @ThaDafinser. Now I do not get a prompt anymore in Firefox and everything works, but I always need to make it work on IE.

  • In IE, I set Local Intranet Security to the lowest, but nothing changed.

  • In IE, "Automatic logon with current user name and password" is checked for Local Intranet & Trusted Sites.

  • When I force IE to ask credentials in a prompt, if I post the prompt, IE does not return the credentials, contrary to Firefox.


Edit 2015-05-13 :

  • I added the URL to trusted sites in IE, nothing changed.

  • I set security to low for trusted sites, nothing changed.

  • I unchecked "Use HTTP 1.1 through proxy connections" in IE > Internet Options > Advanced, I still can not have session informations on Internet Explorer, even if I use the prompt.

  • I added the full URL in Internet Explorer > Internet Options > Security > Local Intranet > Sites > Advanced

  • In Internet Explorer > Internet Options > Security > Local Intranet > Sites > Advanced, I also added the same part of the domain (mycompany.com) than I have added in Firefox to make it work, but this did not help.

Edit 2015-05-18 :

Changed my httpd.conf to be compatible with Apache 2.4, according to what @timclutton said in his answer :

<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>

Edit 2015-05-19 :

  • I tried to set a basic authentication intead of SSPI and it does not work.

    AuthType Basic AuthName "Authentication Required" AuthUserFile "E:/PATH/.htpasswd" Require valid-user

    Order allow,deny Allow from all

解决方案

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.

You can remove the prompt, by changing the Firefox settings:

  • Type: "about:config" in the addressbar
  • Check for network.automatic-ntlm-auth.trusted-uris
  • Set the value to your domain, or part of the domain e.g mycompany.com (seperate with comma multiple values)

For IE you need to set the security settings for your page (intranet) lower than for the rest of the internet. Please see http://superuser.com/questions/148063/why-does-internet-explorer-keep-asking-me-for-ntlm-credentials-in-an-intranet-zo

这篇关于NTLM验证 - 获取在PHP中的Windows登录,域名和主机的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆