5

PHP、Apache、および Windows を実行しています。ドメインの設定がないので、Web サイトのフォームベース認証で、Windows に組み込まれているローカル ユーザー アカウント データベースを使用したいと考えています (SAM と呼ばれていると思います)。

Active Directory がセットアップされている場合、PHP LDAP モジュールを使用してスクリプトで接続および認証できることはわかっていますが、AD がなければ LDAP はありません。スタンドアロン マシンに相当するものは何ですか?

4

3 に答える 3

3

簡単な解決策も見つかりませんでした。CreateObject と WinNT ADSI プロバイダーを使用した例があります。しかし、最終的に は、Active Directory Service Interfaces WinNT プロバイダーでユーザー認証の問題が発生します。100% 確信があるわけではありませんが、WSH/ネットワーク接続アプローチにも同じ問題があると思います。Microsoft オペレーティング システムでユーザー資格情報を検証
する方法によると、LogonUser または SSPI を使用する必要があります。 それはまた言います

LogonUser Win32 API は、Microsoft Windows Server 2003 では TCB 特権を必要としませんが、ダウンレベルの互換性のために、これは依然として最善の方法です。

Windows XP では、LogonUser を呼び出すためにプロセスが SE_TCB_NAME 特権を持っている必要がなくなりました。したがって、Windows XP でユーザーの資格情報を検証する最も簡単な方法は、LogonUser API を呼び出すことです。

したがって、Win9x/2000 のサポートが不要であると確信している場合は、LogonUser を php に公開する拡張機能を作成します。NT アカウントから
のユーザー認証にも興味があるかもしれません 。それは w32api 拡張機能を使用し、サポート dll を必要とします...私はむしろその小さな LogonUser-extension を書きたいと思います;-) それが実現不可能な場合は、おそらく IIS の fastcgi モジュールとその安定性を調べて、 IIS が認証を処理します。

編集: System.Security.Principal.WindowsIdentityと php のcom/.net extension
も利用しようとしました。しかし、dotnet コンストラクターはオブジェクト コンストラクターにパラメーターを渡すことを許可していないようで、GetType() からアセンブリ (およびそれを使用して CreateInstance()) を取得するための「実験」は、「unknown zval」エラーで失敗しました。

于 2008-09-14T09:22:01.387 に答える
0

PHP拡張機能を構築するには、ハードディスク容量に関してかなり大きな投資が必要です。私はすでにGCC(MinGW)環境をインストールしているので、PHPスクリプトからプロセスを起動するというパフォーマンスの打撃を受けることにしました。ソースコードは以下の通りです。

// Usage: logonuser.exe /user username /password password [/domain domain]
// Exit code is 0 on logon success and 1 on failure.

#include <windows.h>

int main(int argc, char *argv[]) {
    HANDLE r = 0;
    char *user = 0;
    char *password = 0;
    char *domain = 0;
    int i;

    for(i = 1; i < argc; i++) {
        if(!strcmp(argv[i], "/user")) {
            if(i + 1 < argc) {
                user = argv[i + 1];
                i++;
            }
        } else if(!strcmp(argv[i], "/domain")) {
            if(i + 1 < argc) {
                domain = argv[i + 1];
                i++;
            }
        } else if(!strcmp(argv[i], "/password")) {
            if(i + 1 < argc) {
                password = argv[i + 1];
                i++;
            }
        }
    }

    if(user && password) {
        LogonUser(user, domain, password, LOGON32_LOGON_BATCH, LOGON32_PROVIDER_DEFAULT, &r);
    }
    return r ? 0 : 1;
}

次は、その使用法を示すPHPソースです。

if($_SERVER['REQUEST_METHOD'] == 'POST') {
    if(isset($_REQUEST['user'], $_REQUEST['password'], $_REQUEST['domain'])) {
        $failure = 1;
        $user = $_REQUEST['user'];
        $password = $_REQUEST['password'];
        $domain = $_REQUEST['domain'];

        if($user && $password) {
            $cmd = "logonuser.exe /user " . escapeshellarg($user) . " /password " . escapeshellarg($password);
            if($domain) $cmd .= " /domain " . escapeshellarg($domain);
            system($cmd, $failure);
        }

        if($failure) {
            echo("Incorrect credentials.");
        } else {
            echo("Correct credentials!");
        }
    }
}
?>
<form action="<?php echo(htmlentities($_SERVER['PHP_SELF'])); ?>" method="post">
    Username: <input type="text" name="user" value="<?php echo(htmlentities($user)); ?>" /><br />
    Password: <input type="password" name="password" value="" /><br />
    Domain: <input type="text" name="domain" value="<?php echo(htmlentities($domain)); ?>" /><br />
    <input type="submit" value="logon" />
</form>
于 2008-09-15T20:07:18.130 に答える
0

良い質問!

私はこれについて少し考えました...そして、良い解決策が思いつきません。私が考えることができるのは、うまくいくかもしれない恐ろしい恐ろしいハックです。この質問に対する回答が 1 日近く投稿されていないことを確認した後、私は悪いと考えましたが、有効な回答であれば問題ありません。

システムの実行中は、SAM ファイルは立ち入り禁止です。機能する可能性のある DLL インジェクションのトリックがいくつかありますが、最終的にはパスワード ハッシュになってしまい、ユーザーが提供したパスワードをハッシュしてそれらと照合する必要があります。

本当に必要なのは、SAM ファイルに対してユーザーを認証しようとするものです。以下のようなことをすればできると思います。

  1. サーバー上にファイル共有を作成し、ログインできるようにしたいアカウントだけがアクセスできるようにします。
  2. PHP では、system コマンドを使用して wsh スクリプトを呼び出します。これにより、Web サイトのユーザーが提供するユーザー名とパスワードを使用して共有をマウントします。動作するかどうかを記録し、動作する場合はドライブをアンマウントします。
  3. なんとか結果をまとめます。結果は、スクリプトの stdout で、またはできればスクリプトの戻りコードを使用して、php に返すことができます。

きれいではないことはわかっていますが、うまくいくはずです。

気持ち悪いです :|

編集: 外部 wsh スクリプトを呼び出す理由は、PHP では UNC パスの使用が許可されていないためです (私が覚えている限り)。

于 2008-09-14T02:13:33.803 に答える