Проверка подлинности на основе форм PHP в Windows с использованием учетных записей локальных пользователей
Я использую PHP, Apache и Windows. У меня нет настройки домена, поэтому я хотел бы, чтобы при проверке подлинности на основе форм моего сайта использовалась локальная база данных учетных записей пользователей, встроенная в Windows (я думаю, она называется SAM).
Я знаю, что если Active Directory настроен, вы можете использовать PHP-модуль LDAP для подключения и аутентификации в вашем скрипте, но без AD нет LDAP. Что является эквивалентом для автономных машин?
3 ответа
Я не нашел и простого решения. Есть примеры использования CreateObject и провайдера WinNT ADSI. Но в конечном итоге все они сталкиваются с проблемами аутентификации пользователя с поставщиком WinNT интерфейсов службы Active Directory. Я не уверен на 100%, но я думаю, что подход WSH/ подключение к сети имеет ту же проблему.
В соответствии с Как проверить учетные данные пользователя в операционных системах Microsoft, вы должны использовать LogonUser или SSPI.
Это также говорит
Поэтому, если бы я был уверен, что поддержка Win9x/2000 не нужна, я бы написал расширение, которое выставляет LogonUser на php.Winon API LogonUser Win32 не требует привилегии TCB в Microsoft Windows Server 2003, однако для обеспечения более низкой совместимости это по-прежнему лучший подход.В Windows XP больше не требуется, чтобы процесс имел привилегию SE_TCB_NAME для вызова LogonUser. Поэтому самый простой метод проверки учетных данных пользователя в Windows XP - это вызов API LogonUser.
Вы также можете быть заинтересованы в аутентификации пользователей из учетных записей NT. Он использует расширение w32api и нуждается в поддержке DLL... Я бы лучше написал это маленькое расширение LogonUser;-)
Если это невозможно, я, вероятно, посмотрю на модуль fastcgi для IIS и на то, насколько он стабилен, и позволю IIS обработать аутентификацию.
редактировать:
Я также пытался использовать System.Security.Principal.WindowsIdentity и расширение php com/.net. Но конструктор dotnet, по-видимому, не позволяет передавать параметры конструктору объектов, и мой "эксперимент" по получению сборки (а вместе с ней CreateInstance()) из GetType() завершился с ошибкой "unknown zval".
Хороший вопрос!
Я подумал об этом... и не могу придумать хорошего решения. То, о чем я могу думать, это ужасный ужасный хак, который может сработать. Увидев, что никто не опубликовал ответ на этот вопрос в течение почти дня, я понял, что это плохо, но с рабочим ответом все будет в порядке.
Файл SAM запрещен во время работы системы. Есть некоторые хитрости DLL-инъекций, которые вы можете использовать, но в итоге вы просто получите хэши паролей и вам придется хэшировать пароли, предоставленные пользователем, чтобы они соответствовали им в любом случае.
То, что вы действительно хотите, это то, что пытается аутентифицировать пользователя по файлу SAM. Я думаю, что вы можете сделать это, выполнив что-то вроде следующего.
- Создайте общий доступ к файлам на сервере и сделайте так, чтобы доступ к нему имели только те учетные записи, для которых вы хотите иметь возможность войти в систему.
- В PHP используйте системную команду для вызова wsh-скрипта, который: монтирует общий ресурс, используя имя пользователя и пароль, предоставленные пользователем веб-сайта. записывает, если он работает, а затем размонтирует диск, если это работает.
- Соберите результат как-нибудь. Результат может быть возвращен 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>