Аутентификация на основе форм PHP в Windows с помощью Учетных записей Локального пользователя

5
задан Martin 13 September 2008 в 14:57
поделиться

3 ответа

Я не нашел простое решение также. Существует использование в качестве примера CreateObject и поставщик WinNT ADSI. Но в конечном счете они все врезаются в проблемы Аутентификации пользователя с Сервисными Интерфейсами Active Directory поставщик WinNT. Я не на 100% уверен, но я предполагаю, что подход подключения WSH/network имеет ту же проблему.
Согласно тому, Как проверить удостоверения пользователя в операционных системах Microsoft, необходимо использовать LogonUser или SSPI.
Это также говорит

LogonUser Win32 API does not require TCB privilege in Microsoft Windows Server 2003, however, for downlevel compatibility, this is still the best approach.

On Windows XP, it is no longer required that a process have the SE_TCB_NAME privilege in order to call LogonUser. Therefore, the simplest method to validate a user's credentials on Windows XP, is to call the LogonUser API.

Поэтому, если бы я был определенной поддержкой Win9x/2000, не необходим, я записал бы расширение, которое подвергает LogonUser php.
Вы могли бы также интересоваться Аутентификацией пользователя из Учетных записей NT. Это использует w32api расширение и нуждается в поддержке dll... Я записал бы что маленькое LogonUser-расширение ;-)
Если бы это не выполнимо, я, вероятно, изучил бы fastcgi модуль для IIS и насколько стабильный это, и позвольте IIS обработать аутентификацию.

править:
Я также попытался использовать Систему. Безопасность. Принципал. WindowsIdentity и com/.net расширение php. Но dotnet конструктор, кажется, не позволяет передающие параметры конструктору объектов, и мой "эксперимент" для получения блока (и с ним CreateInstance ()) от GetType () привел к сбою с "неизвестным zval" ошибку.

3
ответ дан 15 December 2019 в 06:38
поделиться

Хороший вопрос!

Я уделил это некоторое внимание..., и я не могу думать о хорошем решении. То, о чем я могу думать, является ужасным ужасным взломом, который просто мог бы работать. После наблюдения, что никто не отправлял ответ на этот вопрос в течение почти дня, я полагал, что плохой, но рабочий ответ будет в порядке.

Файл SAM от пределов, в то время как система работает. Существуют некоторые приемы Внедрения DLL, которые Вы можете получать работу, но в конце Вы только закончите с хэшами пароля, и необходимо было бы хешировать пользовательские указанные пароли для соответствия против них так или иначе.

То, что Вы действительно хотите, является чем-то, что пытается аутентифицировать пользователя против файла SAM. Я думаю, что можно сделать это путем выполнения чего-то как следующее.

  1. Создайте Долю Файла на сервере и сделайте его так, чтобы только считал это, Вы хотите смочь войти в систему, как предоставленный доступ к нему.
  2. В PHP используют системную команду для вызова wsh сценария что: монтирует долю с помощью имени пользователя и пароля, который обеспечивает пользователь веб-сайта. записи, если это работает и затем размонтировало диск, если это делает.
  3. Соберите результат так или иначе. Результат может быть возвращен к php или на stdout сценария или на надо надеяться использовании кода возврата для сценария.

Я знаю, что это не симпатично, но это должно работать.

Я чувствую себя грязным :|

Править: причина вызова внешнего wsh сценария состоит в том, что PHP не позволяет Вам использовать пути UNC (насколько я могу помнить).

0
ответ дан 15 December 2019 в 06:38
поделиться

Создание расширения 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>
0
ответ дан 15 December 2019 в 06:38
поделиться