如果您需要在使用陰影密碼的系統上驗證 *真實* 的 Unix 密碼,則 PHP 中的 posix_getpwnam() 函式將無法運作(如上所述,「x」或「*」將會位於密碼欄位中)。
我需要在 PHP 中驗證使用者/密碼(使用 SSL!)。我不知道這是否是最好的方法,但這是我目前正在做的事情(效果很好!)。
首先,您需要來自作業系統的一些協助。我編寫了一個微小的 C 實用程式來為我進行陰影查找... 它需要 root 權限才能讀取 /etc/shadow。因此,在編譯(gcc -O2 -s -o spasswd -lcrypt spasswd.c)後,您需要使用 sudo 來執行它,或者
# chown root spasswd && chmod u+s spasswd
我用來從 PHP 驗證使用者/密碼的程式碼看起來像
function Authenticate($realm)
{
global $PHP_AUTH_USER;
global $PHP_AUTH_PW;
if(!isset($PHP_AUTH_USER))
{
header("WWW-Authenticate: Basic realm=\"$realm\"");
header("HTTP/1.0 401 Unauthorized");
return false;
}
else
{
if(($fh = popen("/usr/sbin/spasswd", "w")))
{
fputs($fh, "$PHP_AUTH_USER $PHP_AUTH_PW");
$r = pclose($fh);
if(!$r)
return true;
}
}
header("WWW-Authenticate: Basic realm=\"$realm\"");
header("HTTP/1.0 401 Unauthorized");
return false;
}
spasswd.c 的 C 原始碼
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <crypt.h>
#include <shadow.h>
static char salt[12], user[128], pass[128];
void die(void)
{
memset(salt, '\0', 12);
memset(user, '\0', 128);
memset(pass, '\0', 128);
}
int main(int argc, char *argv[])
{
struct spwd *passwd;
atexit(die); die();
if(fscanf(stdin, "%127s %127s", user, pass) != 2)
return 1;
if(!(passwd = getspnam(user)))
return 1;
strncpy(salt, passwd->sp_pwdp, 11);
strncpy(pass, crypt(pass, salt), 127);
if(!strncmp(pass, passwd->sp_pwdp, 127))
return 0;
return 1;
}
希望這對某人有幫助...