2015-10-04 54 views
0

在我的Grails 2.5.1项目中,我使用的是弹簧安全核心:2.0 RC5插件,收到此错误:编码与Spring Security的Grails的插件密码

Error initializing the application: Cannot invoke method encodePassword() on null object 

这里是我的BootStrap:

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 = { 
    } 
} 

我错过了什么?

回答

3

问题是def springSecurityService的位置。正如你所声明的那样,它是一个闭合的局部变量。它不是依赖注入的候选对象,所以没有初始化它,它是空的。

要使用依赖注入,请将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() } 
    } 
} 

一个更好的方法是将这段代码移到交易服务。这留给读者作为练习。

+0

感谢您的详细回答,您现在明确告诉我,但我正面临一件新事物,除了** userRole **和** adminRole **以外,没有任何数据存储在数据库中,用户没有存储!你有看到代码中的任何东西吗? – Sherif

+0

这可能是一个验证错误 - 您是否向User类添加了新的必需属性?所有属性在默认情况下都是'nullable:false'。我几乎从不使用'failOnError',因为抛出一个验证异常的代价很大,但是当你有硬编码的值时,你希望这里有效(另一种情况是测试中的数据),我会用它来使这个问题很明显,并且要迅速失败。将两个用户的'save()'改为'save(failOnError:true)',它应该显示缺少的内容。 –

+0

雅这是一些验证错误,真的很感谢您的支持,顺便说一句,你有任何有用的和有用的资源,为Grails给我很好的推动,因为我是有经验的Java开发人员,但我是新来的Grails,我需要完成一个小项目。 – Sherif

相关问题