Spring Security 5 以编程方式验证用户名和密码

发布于 2025-01-20 18:28:14 字数 1022 浏览 2 评论 0原文

我有一个 grails 5 Spring Security 应用程序(我最近从 grails 3 迁移了它)。 Spring Security 4+ 使用不同的密码方案,其中包括算法、盐和散列密码,所有这些都在密码字段中分隔,如下所示:“{algorithm}{salt}{hash}”

这一切都很好。我已将“{SHA-256}”附加到现有密码的开头,并且身份验证适用于网络应用程序。

问题是我的应用程序有一个 API 部分,它使用基本身份验证,我在控制器中手动进行身份验证(不使用 spring security)。这很简单且无状态,并且非常适合我的目的。问题是,当我创建 Spring Security 添加盐的新用户时,我无法再验证用户名和密码。

在向新用户添加盐之前有效的旧代码是有效的:

String sha256hex = DigestUtils.sha256Hex(password);
String dbHashedPw = "{SHA-256}${sha256hex}"
user = User.findByUsernameAndPassword(email, dbHashedPw)

这不处理盐或迭代,因此不适用于为新用户生成的密码。

我尝试启用 grails.plugin.springsecurity.useBasicAuth: true (在 application.yml 中),但这可能配置错误,因为它似乎没有效果。

我还尝试改进上面的代码以使用盐并以与 Spring Security 相同的方式进行迭代,但它变得复杂并且似乎不是最好的方法。

我想要的是这样的界面:

boolean springSecurityService.validatePassword(UserDetails userDetails, String password)

Spring Security将从数据库中获取密码并使用描述算法和盐的标记,并对密码进行适当的散列并比较两者,如果密码匹配则返回布尔值。

看起来这应该很简单,但我现在花了一整天的时间来破解它,但没有成功。任何帮助将不胜感激!

I have a grails 5 Spring Security app (that i've recently migrated from grails 3). Spring Security 4+ uses a different password scheme where it includes the algorithm, salt and hashed password all in the password field delimited like so: "{algorithm}{salt}{hash}"

This all works fine. I've appended "{SHA-256}" to the start of existing passwords, and authentication is working for the web app.

The problem is that I have an API section of my app that uses basic auth which I manually authenticate in my controllers (not using spring security). This is simple and stateless and works well for my purposes. Problem is, I can no longer validate usernames and passwords when I create new users which Spring Security adds a salt for.

Old code that worked before adding salt to new users was effectively:

String sha256hex = DigestUtils.sha256Hex(password);
String dbHashedPw = "{SHA-256}${sha256hex}"
user = User.findByUsernameAndPassword(email, dbHashedPw)

This doesn't handle salt, or iterations, so does not work on passwords generated for new users.

I've tried enabling grails.plugin.springsecurity.useBasicAuth: true (in application.yml) but this perhaps was misconfigured since it seemed to have no effect.

I've also tried improving my code above to work with the salt and iterating in the same manner as Spring Security does, but it becomes complicated and doesn't seem like the best way to do it.

What I want is an interface like:

boolean springSecurityService.validatePassword(UserDetails userDetails, String password)

Where Spring Security would grab the password from the database and use the markup describing the algorithm and the salt, and do the appropriate hashing on password and compare the two, returning a boolean if the password matches.

It seems like this should be simple, but I've now spent over a full day hacking around it with no success. Any help would be appreciated!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

始终不够爱げ你 2025-01-27 18:28:15

用我找到的解决方法回答我自己的问题。我找不到我想要的 springSecurityService 接口,但我确实发现我可以通过不在 User.groovy 中调用 spring security 来模拟旧的 grails 3 密码编码,而是执行以下操作:

import org.apache.commons.codec.digest.DigestUtils
...

def beforeInsert() {
    encodePassword()
}

def beforeUpdate() {
    if (isDirty('password')) {
        encodePassword()
    }
}

protected void encodePassword() {
    password = "{SHA-256}" + DigestUtils.sha256Hex(password)
}

注意我依赖于 apache 库: 'commons-codec:commons-codec:1.11' 进行哈希。

当然,应该提到的是,SHA-256 不再被认为是安全的,这只是为了在可以迁移之前实现向后兼容性。

Answering my own question with a workaround I've found. I couldn't find the springSecurityService interface that I wanted, but I did find I could emulate the old grails 3 password encoding by not calling spring security in User.groovy, and instead doing the following:

import org.apache.commons.codec.digest.DigestUtils
...

def beforeInsert() {
    encodePassword()
}

def beforeUpdate() {
    if (isDirty('password')) {
        encodePassword()
    }
}

protected void encodePassword() {
    password = "{SHA-256}" + DigestUtils.sha256Hex(password)
}

Note I'm relying on apache library: 'commons-codec:commons-codec:1.11' to do the hash.

Of course, it should be mentioned that SHA-256 is not considered secure any more and this is only for backwards compatibility before a migration is possible.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文