シングルサインオン(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!";
}
}
}
}
?>
_
このスクリプトはこの構成で動作しています:
しかし、今、私はこれをこの構成に実装する必要があり、機能しません:
この状態のため、「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"有効なユーザーが必要
注文を許可、拒否をすべてから許可
Firefoxで試してみると、ログインとパスワードのプロンプトが表示されます。プロンプトを投稿すると、スクリプトはプロンプトからログインを取得しますが、これは私がやりたいことではありません。これをIEで動作させるために取得する必要があり、ログイン名とパスワードを再度入力する必要はありません。現在のWindowsセッションのログインが必要です。
プロンプトを削除するには、Firefoxの設定を変更します。
IEの場合、ページ(イントラネット)のセキュリティ設定をインターネットの他の部分よりも低く設定する必要があります。以下を参照してください https://superuser.com/questions/148063/why-does-internet-Explorer-keep-asking-me-for-ntlm-credentials-in-an-intranet-zo
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>