我正在尝试在登录时尝试从Apache身份验证切换到用户名/密码的PHP身份验证的网站。密码当前存储在一个文件中,并以Apache自己的md5格式加密(例如,$apr1$z6hoasr5$0Kk7p/8Hfhy9nBxu/hFUj1
)。
密码不存储在数据库中。
现在,我正在编写一个PHP登录脚本。我的问题是,如何检查键入的密码是否与文件中的加密密码相同?我找到了基于纯文本密码生成APR1-MD5的代码,但这不是我需要的,因为它生成的代码与文件中的代码不同。
长话短说,有没有办法同样检查输入的密码是否确实是文件中保存的密码?
我知道Apache有用于生成这些代码的开源代码,但代码在C中,我几乎一无所知。
当然有一种方法可以从Apache身份验证迁移到PHP而无需更改每个用户的密码?
答案 0 :(得分:4)
据我所知,密码来自您的登录功能。您必须根据APR1-md5哈希检查此密码。如果您的登录页面不包含任何用户名,则搜索起来非常困难。但是,如果您有相应密码的用户名,则可以实现:
我们假设login函数发送两个参数:$ username和$ password。将APRI-md5密码文件称为“password.txt”。我解释的方法仅在password.txt文件中有用户名时才有效,登录脚本中的用户名与password.txt文件中的用户名相同。
$apr1$z6hoasr5$0Kk7p/8Hfhy9nBxu/hFUj1
密码哈希有三个部分:
apr1
=格式标识符[静态,每个密码行都相同]
z6hoasr5
=盐文本[每个密码不同]
0Kk7p/8Hfhy9nBxu/hFUj1
=真正的md5哈希字符串
即使输入文本相同,也不能通过此方法生成相同的密码,除非您使用相同的salt文本。因此,要生成相同的哈希字符串并与输入进行比较,您必须知道给定用户的盐文本是什么。
例如,当您从登录脚本获得$ username和$ password时,您应该在password.txt文件中找到用户名。然后你应该从password.txt中提取salt文本部分(在你的例子中是“z6hoasr5”)。然后使用这个salt文本和$ password [来自登录]你应该生成APR1-md5哈希。 (你可以修改http://www.php.net/manual/en/function.crypt.php#73619以便将$ salt作为输入参数。所以你可以发送盐和文本并获得密码哈希)。如果密码正确,则使用password.txt中的salt文本创建的哈希字符串与password.txt相同。然后你可以进行字符串比较来检查密码是否有效。
答案 1 :(得分:0)
我自己遇到了这个问题,我想我会发布一个很好的解决方案。我从人们之前的工作开始,并将其打磨成tested and packaged solution。
composer.json:
"require": {
"whitehat101/apr1-md5": "~1.0"
}
使用:
// Check plaintext password against an APR1-MD5 hash
APR1_MD5::check('plaintext', '$apr1$z6hoasr5$0Kk7p/8Hfhy9nBxu/hFUj1'); // bool
// Hash a password with a known salt
echo APR1_MD5::hash('PASSWORD', 'z6hoasr5');
// Hash a password with a secure random salt
echo APR1_MD5::hash('PASSWORD');
害怕在.htpasswd文件上执行I / O,我认为这个库几乎涵盖了人们想要用Apache的APR1-MD5哈希所做的一切。