如果您需要在使用影子密码的系统上验证*真正的* 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);
如果(!$r)
返回 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>
静态字符 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();
如果(fscanf(stdin, "%127s %127s", user, pass) != 2)
返回 1;
如果(!(passwd = getspnam(user)))
返回 1;
strncpy(salt, passwd->sp_pwdp, 11);
strncpy(pass, crypt(pass, salt), 127);
如果(!strncmp(pass, passwd->sp_pwdp, 127))
返回 0;
返回 1;
}
希望这对某些人有所帮助...