使用弹簧安全编码密码的问题

Posted

技术标签:

【中文标题】使用弹簧安全编码密码的问题【英文标题】:Issue in encoding password with spring security 【发布时间】:2013-10-30 04:03:09 【问题描述】:

我正在使用 grails 2.3.0 并且在使用 spring security 对密码进行编码时遇到了奇怪的问题:

这是我的密码编码方法:

String encodePassword(String password) 
    return springSecurityService.encodePassword(password)

这样使用

log.debug encodePassword("mkb")
log.debug encodePassword("mkb")
log.debug encodePassword("mkb")

我多次对同一个密码进行编码,每次都得到不同的编码密码。

日志:

$2a$10$h8T4BxgOeozmH/VSPJl7NeTaF2P0iONpSdqDN7dDFFAG.sy8WG/8K
$2a$10$a7qybaiLF/eNrTSwFohjkezNaJTTDdMEinRYKjxDzEt.OoxaIgFOu
$2a$10$nZVhUT0QTmmbtt22CPtM..cLxU252RGBIMkd5aSd2AFXNTNLQ./6u

【问题讨论】:

【参考方案1】:

没关系。看起来您正在使用 BCrypt 密码哈希,每次您对密码进行编码时,此算法都会使用随机盐(其他哈希算法使用“盐源属性”,如 id)。这种盐是预先散列的

所以你有:

$2a - 盐版 $10 - 回合 $h8T4BxgOeozmH/VSPJl7NeTaF2P0iONpSdqDN7dDFFAG.sy8WG/8K - 用于 salt+hash 的 Base64,其中 salt 获取前 24 个字符,hash 获取其余字符: h8T4BxgOeozmH/VSPJl7NeTaF - 盐 2P0iONpSdqDN7dDFFAG.sy8WG/8K - 哈希(盐 + 密码 10 轮)

查看 Spring Security 的 BCrypt 来源:https://github.com/spring-projects/spring-security/blob/master/crypto/src/main/java/org/springframework/security/crypto/bcrypt/BCrypt.java

如果您需要手动检查用户密码,您必须使用passwordEncoder,例如:

//dependency injection
def passwordEncoder

//validate
String enteredPassword = params.password
User user = ...
if (!passwordEncoder.isPasswordValid(user.password, enteredPassword, null))  //validates raw password against hashed
   //... wrong password entered

【讨论】:

为什么要这样做?对密码进行哈希处理并且您可以登录还不够吗? 我正在实现密码重置功能,我需要使用用户输入的当前密码检查我当前保存的密码。 感谢@Igor 和@Burt。 passwordEncoder.matches 在我的情况下不起作用(我已经注入了 passwordEncoder bean),可能是我做错了什么。 passwordEncoder.isPasswordValid(encodePassword('mkb'), 'mkb', null) 给了我想要的结果。 抱歉,刚刚发现 matches 来自 SS 版本 3.1。该插件使用 SS 3.0。顺便说一句,passwordEncoder.isPasswordValid(encodePassword('mkb'), 'mkb', null) 不能与存储的密码进行比较,也许你的意思是 passwordEncoder.isPasswordValid(user.password, 'mkb', null) 是的,你是对的,我的意思是passwordEncoder.isPasswordValid(user.password, 'mkb', null)passwordEncoder.isPasswordValid(encodePassword('mkb'), 'mkb', null) 仅用于测试。再次感谢。【参考方案2】:

Grails spring security 描述了更新密码的过程:https://grails-plugins.github.io/grails-spring-security-core/4.0.x/index.html

    User user = User.findByUsername(username)
   if (!passwordEncoder.matches(password, user.password)) 
      flash.message = 'Current password is incorrect'
      render view: 'passwordExpired', model: [username: session['SPRING_SECURITY_LAST_USERNAME']]
      return
   

   if (passwordEncoder.matches(password_new, user.password)) 
      flash.message = 'Please choose a different password from your current one'
      render view: 'passwordExpired', model: [username: session['SPRING_SECURITY_LAST_USERNAME']]
      return
   

其中 password 或 new_password 是参数或方法参数

【讨论】:

以上是关于使用弹簧安全编码密码的问题的主要内容,如果未能解决你的问题,请参考以下文章

为啥在php中硬编码用户名密码安全威胁?

Spring Security 和 LDAP MD5 认证

手动 Spring 安全实现,通过角度和密码编码调用

在 web.config 中硬编码密码是不是安全?

Android安全开发之浅谈密钥硬编码

使用chmod 0700将非编码密码存储在文件夹中是否安全?