ASP.NET应用中是否应哈希存储密码重置令牌?
应该对密码重置令牌进行哈希后存储吗?
绝对应该——这其实是密码安全领域的标准实践,放到密码重置令牌场景下完全适用,甚至可以说必须这么做。下面给你拆解原因和ASP.NET里的实现思路:
为什么要哈希令牌?
- 令牌本质是「一次性临时凭证」:用户拿到令牌后,相当于用它来证明身份并重置密码,和用户的登录密码性质完全一致——如果明文存储,一旦数据库被非法访问,攻击者可以直接拿着令牌发起密码重置请求,完全绕过任何其他验证。
- 随机性再高也没用:哪怕你生成的是128位的随机字符串,只要明文存在数据库里,拖库后攻击者不需要任何破解就能直接使用,风险和明文存储用户密码一模一样。
- 可逆加密不如哈希:有人可能会想“我加密令牌不行吗?”但加密需要密钥,一旦密钥泄露(比如配置文件被读取),攻击者可以轻松解密出明文令牌;而哈希是单向操作,只要用了带加盐的安全哈希算法(比如PBKDF2、Argon2),就算拿到哈希值也无法还原出明文令牌。
ASP.NET里怎么实现?
别自己造轮子,直接用框架自带的工具就能搞定:
- 生成令牌时:
- 用
RandomNumberGenerator生成足够长的随机明文令牌(比如32字节,转成Base64字符串,绝对不要用不安全的Random类); - 把明文令牌返回给用户(比如通过邮件发送);
- 用ASP.NET Identity的
PasswordHasher<TUser>对明文令牌进行哈希,把哈希值+过期时间存到数据库里。
- 用
- 验证令牌时:
- 用户提交令牌后,从数据库中取出对应的哈希值和过期时间;
- 先检查令牌是否过期,过期直接拒绝;
- 调用
PasswordHasher.VerifyHashedPassword方法,验证用户提交的明文令牌和数据库中的哈希值是否匹配,匹配则允许重置密码。
额外的安全注意事项
- 必须设置令牌过期时间:一般15-60分钟足够,就算令牌哈希泄露,过期后也无法使用;
- 验证通过后立即删除令牌哈希:避免同一令牌被重复使用;
- 不要用简单哈希算法:比如MD5、SHA1,ASP.NET的
PasswordHasher默认用的是PBKDF2,已经是符合安全标准的算法,不要替换成更弱的。
内容的提问来源于stack exchange,提问作者Arad




