我是第一次用PHP编写Web服务并遇到了一些安全问题。
1)我打算在将密码写入数据库(或验证用户)之前使用md5()散列密码但我意识到要这样做,我必须以明文形式将密码传输到服务器并且在那里哈希。
因为这个我想到md5()用javascript客户端进行,然后在服务器上重新进行,但是如果javascript被禁用,那么用户无法登录,对吧?
2)我听说过任何操作只读时,你应该使用GET,但是如果它修改了数据库,你应该使用POST。是不是像GET一样透明,只是不在地址栏中?
答案 0 :(得分:5)
通常不建议您实现自己的哈希图层。如果您只是为了学习目的而做一个非常小的网站,我肯定md5会没问题,但如果您要为更大的网站存储重要信息,您应该使用库,例如PHPass:
感谢Jacco提供的PHPass代码片段:
require('PasswordHash.php');
$pwdHasher = new PasswordHash(8, FALSE);
// $hash is what you would store in your database
$hash = $pwdHasher->HashPassword( $password );
// $hash would be the $hashed stored in your database for this user
$checked = $pwdHasher->CheckPassword($password, $hash);
if ($checked) {
echo 'password correct';
} else {
echo 'wrong credentials';
}
如果你坚持自己做,你应该加密密码。请参阅http://phpsec.org/articles/2005/password-hashing.html。
define('SALT_LENGTH', 9);
function generateHash($plainText, $salt = null)
{
if ($salt === null)
{
$salt = substr(md5(uniqid(rand(), true)), 0, SALT_LENGTH);
}
else
{
$salt = substr($salt, 0, SALT_LENGTH);
}
return $salt . sha1($salt . $plainText);
}
GET和POST之间差异的原因是浏览器解释请求的方式。如上所述,Web爬网程序不会执行POST请求。但想象一下,您访问了网站http://example.com/deleteuser.php?userid=25
上的某个页面,删除了一个讨厌的垃圾邮件发送者。然后关闭浏览器。下次你回来时,firefox重新打开那个页面,你很遗憾地删除了刚刚注册的用户!
GET与POST的另一个原因是对cross-site request forgeries的部分预防。如果您有一个在GET请求中注销用户的页面,则有人可能会将图像标记嵌入到评论或论坛帖子中,如<img src="http://example.com/logout.php" />
,并且浏览器将被强制执行注销操作。因此,任何查看该页面的用户都将被注销,即使他们是管理员。
编辑:顺便说一下,你应该使用sha-256或bcrypt而不是md5,它已被破解(?)。
答案 1 :(得分:1)
1)我打算在将密码写入数据库(或验证用户)之前使用md5()散列密码但我意识到要这样做,我必须以明文形式将密码传输到服务器并且哈希吧。
因为这个我想到md5()用javascript客户端然后在服务器上重新进行,但是如果javascript被禁用,那么用户无法登录,对吧?
散列密码的重点是减少数据库暴露的后果。如果您在客户端哈希,则只需更改客户端必须发送的一个字符串以获取其他字符串。这毫无意义。
2)我听说过任何操作只读时,你应该使用GET,但是如果它修改了数据库,你应该使用POST。是不是像GET一样透明,只是不在地址栏中?
抓取工具(包括搜索引擎索引器)不会发出POST请求。浏览器通常会警告用户重新提交POST数据。
使用POST和GET来做正确的事情不是安全问题。