我遇到一种情况,我有两个服务器位于负载均衡器后面。我使用password_hash()在一台服务器上生成密码。
基本上是这样的
password_hash('XXXXXXXXX', PASSWORD_DEFAULT);
在我的应用程序中,当我向使用服务器1的端点发送使用password_verify()的端点的请求时,密码已正确验证并验证了请求,但是当负载平衡器将请求发送到服务器2时password_verify( )似乎无法验证密码。
我已验证两台服务器都使用完全相同的PHP版本,并在同一天运行PHP 7.1.2进行编译。这里还有我想念的东西吗?
答案 0 :(得分:0)
从
详细了解了password_hash
string password_hash ( string $password , int $algo [, array $options ] )
我发现使用password_hash('XXXXXXXXX', PASSWORD_DEFAULT);
不适用于负载平衡,至少在没有大量修改功能或滚动自己的版本的情况下如此。
PASSWORD_DEFAULT
输出特定于该实例的哈希密码,除了在php7 +中salt选项已弃用
直到{php1}才添加$algo
(如Argon2i)的更多选项,因此您需要从php7.1升级,因为目前唯一的选择是使用bycrypt,而唯一的选择是使用成本。
http://php.net/manual/en/password.constants.php
无论采用哪种方式,即使对于负载均衡oauth服务器,这仍然是一个持续存在的问题。服务器1上生成的令牌不适用于服务器2的情况。 解决此问题的一种方法是使用共享的缓存和数据库,这破坏了将负载平衡到单独的硬件甚至不同网络的目的。 另一个选项是在负载均衡器上使用粘性功能。
绝对要避免的一件事是对哈希使用相同的盐来解决此问题。如果您使用相同的数据库,则按照以下步骤进行哈希处理应该可以在所有服务器上正常工作。
使用CSPRNG或生成随机盐的任何其他方法生成长随机盐。有趣的旁注是硬件/物理随机数生成器,例如Lavarand。 将盐添加到密码中,并使用标准密码哈希函数(例如Argon2i)对其进行哈希处理。 将盐和哈希值都保存在用户的数据库记录中。
从数据库中检索用户的盐和哈希值。 将盐添加到给定的密码之前,并使用相同的哈希函数对其进行哈希处理。 将给定密码的哈希与数据库中的哈希进行比较。如果它们匹配,则密码正确。否则,密码不正确。
例如---
<?php
$salt = random_bytes(100);
$password = 'password';
$combined = '$password' + $salt;
$hash = password_hash('$combined', PASSWORD_DEFAULT);
if (password_verify('$combined', $hash)) {
echo 'true';
} else {
echo 'no go';
}
答案 1 :(得分:0)
这两个服务器似乎不支持相同的算法,server1可能会计算Argon2哈希,而server2尚不知道此算法。
您可以暂时修复算法,这将解决问题,直到两台服务器都了解这两种算法为止,然后应切换回PASSWORD_DEFAULT
。
password_hash('XXXXXXXXX', PASSWORD_BCRYPT);