2015-10-04 36 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

相關問題