web-dev-qa-db-ja.com

NTLM認証-Windowsログイン、ドメイン、ホストをPHP

シングルサインオン(SSO)PHPアプリケーションに取り組んでいます。
ユーザーは自分のWindowsセッションにログインし、自分の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!";
            }
        }
    }
}
?>
_

このスクリプトはこの構成で動作しています:

  • Windowsサーバー2003
  • Mod_auth_sspiモジュールを備えたApache 2.2

しかし、今、私はこれをこの構成に実装する必要があり、機能しません:

  • Windowsサーバー2008
  • モジュールmod_authnz_sspiを使用したApache 2.4.6

この状態のため、「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を編集:

  • 次のように、phpで 'whoami'コマンドを実行しようとしました:echo exec('whoami');-> cmd.exeでこのコマンドを実行すると、現在ログに記録されているユーザーが取得されますが、PHPで実行すると、 nt_authority/system。

  • PHP= 'whoami'コマンドを実行すると、WindowsはApacheサービスのログインを確認すると思います。[ログオン]タブでApacheプロパティにアクセスし、有効なユーザーとしてログオンしますPHPがecho exec('whoami');を実行すると、現在のユーザーではなく、Apacheに使用されるログインのみが取得されます。

  • Internet Explorer 8を使用してPHPスクリプトを実行しています。

  • 私はこれを私のApache httpd.confに持っています(__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を編集:

  • マシンにドメインユーザーとしてログインしています

  • Firefoxで試してみると、ログインとパスワードのプロンプトが表示されます。プロンプトを投稿すると、スクリプトはプロンプトからログインを取得しますが、これは私がやりたいことではありません。これをIEで動作させるために取得する必要があり、ログイン名とパスワードを再度入力する必要はありません。現在のWindowsセッションのログインが必要です。

  • Firefoxでは、about:configにアクセスして、@ ThaDafinserのおかげでnetwork.automatic-ntlm-auth.trusted-urisをドメインに設定しました。 Firefoxでプロンプトが表示されなくなり、すべてが機能するようになりましたが、常にIEで機能させる必要があります。

  • IEでは、ローカルイントラネットセキュリティを最低に設定しましたが、何も変わりませんでした。

  • IEでは、「現在のユーザー名とパスワードによる自動ログオン」がローカルイントラネットと信頼済み​​サイトに対してチェックされます。

  • IEプロンプトで資格情報を要求する場合、プロンプトを投稿すると、IEはFirefoxとは逆に資格情報を返しません。


2015-05-13を編集:

  • IEの信頼済みサイトにURLを追加しましたが、何も変更されていません。

  • 信頼できるサイトのセキュリティを低く設定しましたが、何も変わりません。

  • IE> Internet Options> Advancedで[Use HTTP 1.1 through proxy connections]をオフにしました。プロンプトを使用しても、Internet Explorerでセッション情報を取得できません。

  • Internet Explorer>インターネットオプション>セキュリティ>ローカルイントラネット>サイト>詳細設定で完全なURLを追加しました

  • Internet Explorer>インターネットオプション>セキュリティ>ローカルイントラネット>サイト>詳細設定で、Firefoxで追加したのと同じ部分(mycompany.com)も追加して機能させましたが、これは役に立ちませんでした。

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を編集:

  • SSPIの代わりに基本認証を設定しようとしましたが、機能しません。

    AuthType Basic AuthName "Authentication Required" AuthUserFile "E:/ [〜#〜] path [〜#〜] /。htpasswd"有効なユーザーが必要

    注文を許可、拒否をすべてから許可

16
Maxime Mettey

Firefoxで試してみると、ログインとパスワードのプロンプトが表示されます。プロンプトを投稿すると、スクリプトはプロンプトからログインを取得しますが、これは私がやりたいことではありません。これをIEで動作させるために取得する必要があり、ログイン名とパスワードを再度入力する必要はありません。現在のWindowsセッションのログインが必要です。

プロンプトを削除するには、Firefoxの設定を変更します。

  • アドレスバーに「about:config」と入力します
  • Network.automatic-ntlm-auth.trusted-urisを確認します
  • 値をドメインまたはドメインの一部に設定します(例:mycompany.com)(複数の値をコンマで区切る)

IEの場合、ページ(イントラネット)のセキュリティ設定をインターネットの他の部分よりも低く設定する必要があります。以下を参照してください https://superuser.com/questions/148063/why-does-internet-Explorer-keep-asking-me-for-ntlm-credentials-in-an-intranet-zo

4
ThaDafinser

mod_authnz_sspiモジュールは、認証プロセスのすべての側面を透過的に処理します。つまり、PHP認証スクリプトは必要ありません。モジュールが正しく構成されている場合は、単純に参照できるはずです。スクリプト内の$_SERVER['REMOTE_USER']。認証できないユーザーは、標準のApache 403 - Forbiddenエラーを受け取ります。

Apache 2.2のhttpd.conf構文を使用しているため、問題はallow/denyにあると思われ、これはApache 2.4では機能しません(mod_access_compatモジュールが有効になっていない場合)。 Apacheドキュメントの 2.2から2.4へのアップグレード を読んでください。

E:/_PATH_がPHPスクリプトが実行されているフォルダであり、そのパスへのすべてのリクエストで認証が必要になることを確認してください。

以下は、Apache 2.4で動作します。

<Directory "/path/to/webroot">
    AllowOverride     All
    Options           ExecCGI
    # since I run PHP via mod_fcgi; should also work as 'Options none'.

    AuthName          "SSPI Authentication"
    AuthType          SSPI
    SSPIAuth          On
    SSPIAuthoritative On
    SSPIOmitDomain    On
    Require           valid-user
    Require           user "NT AUTHORITY\ANONYMOUS LOGON" denied
</Directory>
2
timclutton