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

StackOverflow https://stackoverflow.com/questions/60585

Вопрос

Я использую PHP, Apache и Windows.У меня нет настройки домена, поэтому я хотел бы, чтобы проверка подлинности на основе форм моего веб-сайта использовала базу данных локальных учетных записей пользователей, встроенную в Windows (я думаю, она называется SAM).

Я знаю, что если настроен Active Directory, вы можете использовать модуль PHP LDAP для подключения и аутентификации в своем скрипте, но без AD LDAP не будет.Что является эквивалентом для автономных машин?

Это было полезно?

Решение

Я тоже не нашел простого решения.Есть примеры использования CreateObject и поставщика WinNT ADSI.Но в конце концов они все сталкиваются Проблемы аутентификации пользователя с поставщиком WinNT интерфейсов службы Active Directory.Я не уверен на 100%, но я предполагать подход WSH/сетевое соединение имеет ту же проблему.
В соответствии с Как проверить учетные данные пользователя в операционных системах 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.

В Windows XP больше не требуется, чтобы процесс имел привилегию SE_TCB_NAME для вызова LogonUser.Таким образом, самый простой способ проверки учетных данных пользователя в Windows XP — это вызов API LogonUser.

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

редактировать:
Я также пытался использовать System.Security.Principal.WindowsIdentity и php расширение com/.net.Но конструктор dotnet, похоже, не позволяет передавать параметры конструктору объектов, и мой «эксперимент» по получению сборки (и вместе с ней CreateInstance()) из GetType() завершился неудачно с ошибкой «неизвестного zval».

Другие советы

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

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

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

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

  1. Создайте общий файловый ресурс на сервере и сделайте так, чтобы доступ к нему предоставлялся только учетным записям, под которыми вы хотите иметь возможность войти в систему.
  2. В PHP используйте системную команду для вызова сценария wsh, который:монтирует общий ресурс, используя имя пользователя и пароль, предоставленные пользователем веб-сайта.записывает, работает ли он, а затем отключает диск, если работает.
  3. Соберите результат как-нибудь.Результат может быть возвращен в 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 с атрибуция
Не связан с StackOverflow
scroll top