使用 Spring Security Grails 插件编码密码
Posted
技术标签:
【中文标题】使用 Spring Security Grails 插件编码密码【英文标题】:Encoding a password with the Spring Security Grails plugin 【发布时间】:2016-01-01 13:31:12 【问题描述】:在我的 Grails 2.5.1 项目中,我使用 spring-security-core:2.0-RC5 插件并收到此错误:
Error initializing the application: Cannot invoke method encodePassword() on null object
这是我的引导程序:
class BootStrap
def init = servletContext ->
def springSecurityService
def userRole = SecurityRole.findByAuthority("ROLE_USER") ?: new SecurityRole(authority:"ROLE_USER").save(flush:true)
def adminRole = SecurityRole.findByAuthority("ROLE_ADMIN") ?: new SecurityRole(authority:"ROLE_ADMIN").save(flush:true)
def user = new User(username:"user" ,password:springSecurityService.encodePassword("123"),enable:true ).save(flush:true)
def admin = new User(username:"admin" ,password:springSecurityService.encodePassword("1234"),enable:true ).save(flush:true)
SecurityUserSecurityRole.create(user, userRole)
SecurityUserSecurityRole.create(admin, adminRole)
def destroy =
我缺少什么吗?
【问题讨论】:
【参考方案1】:问题是def springSecurityService
的位置。正如您声明的那样,它是 init
闭包的局部变量。它不是依赖注入的候选对象,所以没有初始化它,它是空的。
要使用依赖注入,请将 bean 声明为类范围属性,而不是局部变量(闭包或方法)。这样做的原因是 Groovy 编译器将属性声明转换为带有 getter 和 setter 的私有字段。 Spring 不支持 Groovy 属性,但是当有一个与 bean 名称一致的 setter 方法时,它可以按名称自动装配(这是 Grails 的默认设置)。因此,由于 Groovy 编译器为您添加了一个 void setSpringSecurityService(springSecurityService)
方法,Spring 会看到它并调用它,因为该方法的“属性”名称与您想要的 bean 匹配。如果你声明一个局部变量,它会被完全忽略。
所以你的代码应该是这样的:
def springSecurityService
def init = servletContext ->
...
但是您的代码会遇到第二个问题。假设您没有更改 User
类中的自动哈希逻辑,您将编码两次。一次在 BootStrap 中,然后在域类中。如果您这样做,没有人将能够进行身份验证。选择一个 - 像您正在做的那样明确地散列并从域类中删除代码,或者留下域类代码并设置明文密码。如果您选择选项 #2,您的代码(也被清理以使用 findOrSaveBy
并用一个替换所有那些不必要的急切刷新调用)应该看起来像
class BootStrap
def init =
def userRole = SecurityRole.findOrSaveByAuthority('ROLE_USER')
def adminRole = SecurityRole.findOrSaveByAuthority('ROLE_ADMIN')
def user = new User(username: 'user' ,password: '123').save()
def admin = new User(username: 'admin' ,password: '1234').save()
SecurityUserSecurityRole.create(user, userRole)
SecurityUserSecurityRole.create(admin, adminRole)
User.withSession it.flush()
更好的方法是将此代码移至事务服务。这留给读者作为练习。
【讨论】:
感谢您的详细回答,您现在已经对我说清楚了,但我面临着一个新事物,除了 userRole 和 之外没有任何内容存储在数据库中adminRole,不存储用户!!你在代码中看到什么了吗? 这可能是一个验证错误 - 您是否向User
类添加了新的必需属性?所有属性默认为nullable:false
。我几乎从不使用failOnError
,因为抛出验证异常的成本很高,但是当你有硬编码的值时,你希望像这里一样有效(另一种情况是测试中的数据),我会用它来制作问题很明显,而且很快就失败了。将两个用户的 save()
更改为 save(failOnError: true)
,它应该会显示缺少的内容。
是的,这是一些验证错误,非常感谢您的支持,顺便说一下,您是否有任何有用和有用的 Grails 资源来给我很好的推动,因为我是经验丰富的 Java 开发人员,但我是新手到 Grails,我需要用它完成一个小项目。
参见grails.org/wiki/Books 的书籍 - “Grails 2 权威指南”和“Grails in Action”是最全面的以上是关于使用 Spring Security Grails 插件编码密码的主要内容,如果未能解决你的问题,请参考以下文章
Grails - grails-spring-security-rest - 无法从 application.yml 加载 jwt 机密
使用 Spring Security Grails 插件编码密码
Grails + spring-security-core:用户登录后如何分配角色?