Проверка подлинности на основе форм PHP в Windows с использованием учетных записей локальных пользователей - PullRequest
5 голосов
/ 13 сентября 2008

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

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

Ответы [ 3 ]

3 голосов
/ 14 сентября 2008

Я не нашел и простого решения. Есть примеры использования 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.</p>

<p>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 обрабатывать аутентификацию.

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

0 голосов
/ 16 сентября 2008

Создание расширения 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 голосов
/ 14 сентября 2008

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

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

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

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

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

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

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

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

...