簡體   English   中英

使用本地用戶帳戶在Windows上進行基於PHP表單的身份驗證

[英]PHP Forms-Based Authentication on Windows using Local User Accounts

我正在運行PHP,Apache和Windows。 我沒有域設置,所以我希望我的網站基於表單的身份驗證使用Windows內置的本地用戶帳戶數據庫(我認為它稱為SAM)。

我知道如果設置了Active Directory,您可以使用PHP LDAP模塊在腳本中進行連接和身份驗證,但是沒有AD,就沒有LDAP。 獨立機器的等價物是什么?

我也沒有找到一個簡單的解決方案。 有一些使用CreateObject和WinNT ADSI提供程序的示例。 但最終他們都遇到了Active Directory服務接口WinNT提供商的用戶身份驗證問題 the WSH/network connect approach has the same problem. 我不是100%肯定,但我 WSH /網絡連接方法有同樣的問題。
根據如何在Microsoft操作系統上驗證用戶憑據,您應該使用LogonUser或SSPI。
它還說

  LogonUser Win32 API在Microsoft Windows Server 2003中不需要TCB權限,但是,對於下層兼容性,這仍然是最好的方法。 

\n\n

在Windows XP上,不再需要進程具有SE_TCB_NAME權限才能調用LogonUser。 因此,在Windows XP上驗證用戶憑據的最簡單方法是調用LogonUser API。

因此,如果我確定不需要Win9x / 2000支持,我會編寫一個將LogonUser暴露給php的擴展。
您可能還對NT帳戶的用戶身份驗證感興趣。 它使用w32api擴展,需要一個支持dll ...我寧願寫那個小的LogonUser-extension ;-)
如果這不可行,我可能會查看IIS的fastcgi模塊以及它的穩定性,讓IIS處理身份驗證。

編輯:
我也嘗試過使用System.Security.Principal.WindowsIdentity和php的com / .net擴展名 但是dotnet構造函數似乎不允許將參數傳遞給對象構造函數,而我的“實驗”從GetType()獲取程序集(以及它的CreateInstance())失敗並出現“未知zval”錯誤。

好問題!

我已經考慮過這個了......我想不出一個好的解決方案。 我能想到的是一個可怕的可怕的黑客攻擊。 在看到近一天沒有人發布這個問題的答案之后,我覺得很糟糕,但是工作的答案還可以。

系統運行時,SAM文件不受限制。 有一些DLL注入技巧,你可能會工作,但最終你將最終得到密碼哈希,你必須哈希用戶提供的密碼,以匹配他們無論如何。

您真正想要的是嘗試根據SAM文件對用戶進行身份驗證。 我認為您可以通過執行以下操作來完成此操作。

  1. 在服務器上創建文件共享並使其成為只有您希望能夠登錄的帳戶才被授予訪問權限。
  2. 在PHP中,使用system命令調用wsh腳本:使用網站用戶提供的用戶名和密碼來安裝共享。 記錄是否有效,然后卸載驅動器(如果有)。
  3. 以某種方式收集結果。 結果可以在腳本的stdout上返回到php,或者希望使用腳本的返回代碼。

我知道它不漂亮,但應該有效。

我覺得很臟:|

編輯:調用外部wsh腳本的原因是PHP不允許你使用UNC路徑(據我所知)。

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM