2013-11-22 96 views
0

我在這個問題上花了數小時而沒有找到解決方案。其他問題接近,但沒有建議的解決方案爲我工作。Grails試圖驗證編碼密碼(Spring Security Core)

我上運行
- Groovy的2.0.8和
- - Grails的2.1.1
安裝了Oracle的Java v 1.6.0_45(也試圖與1.7的話)

我增加了Spring Security Core Plugin v 2.0-RC2。
我是Grails初學者,我想要做的就是使用我自己的密碼驗證器創建一個帶有密碼的「Runner」。

這是我Runner.groovy中域類(沒有非常從默認的Spring Security的用戶模板除了重命名更改):

package de.muden.runnerbase 

class Runner { 

transient springSecurityService 

String username 
String password 
boolean enabled = true 
boolean accountExpired 
boolean accountLocked 
boolean passwordExpired 

Date dateCreated 
Profile profile 

public static final int MIN_PASS_LENGTH = 6 
public static final int MAX_PASS_LENGTH = 20 

static transients = ['springSecurityService'] 

static constraints = { 
    username(size:3..20,unique:true) 
    password(nullable:false, blank:false, minSize:6, validator: { passwd, runner -> 
     return (passwd != runner.username && validatePasswordInplace(passwd)) 
    }) 
    dateCreated() 
    profile(nullable:true) 
} 

static mapping = { 
    profile lazy:false 
    runs sort:'dateCreated' 
    password column: '`password`' 
} 

Set<Role> getAuthorities() { 
    UserRole.findAllByUser(this).collect { it.role } as Set 
} 

def beforeInsert() { 
    encodePassword() 
} 

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

String toString() { 
    return "Runner '$username'" 
} 

protected void encodePassword() { 
    password = springSecurityService.encodePassword(password) 
} 

protected static boolean validatePasswordInplace(String passToValidate) { 
    println "VALIDATING PASS $passToValidate" 
    return passToValidate ==~ /([A-Za-z0-9äöüÄÖÜß.!\?_-]){$MIN_PASS_LENGTH,$MAX_PASS_LENGTH}/ 
} 

static hasMany = [runs: Run, shoes: Shoe] 
} 

所以驗證允許6個到20個字符之間的密碼長,大寫和小寫字母,數字和一些特殊字符。 簡單的單元測試只是測試這種方法工作正常。

現在一個簡單的集成測試:

void testValidRunner() { 
    Runner r = new Runner(username:'dummy',password:'foobar') 
    assertTrue r.validate() // OK 
    assertFalse r.hasErrors() // OK   
    assertNotNull r.save(flush:true,failOnError:true)  // OK 

    Runner foundRunner = Runner.findByUsername("dummy") 
    assertNotNull foundRunner   // fails, foundRunner = null 
    assertEquals('dummy',foundRunner.username) 
} 

和控制檯(帶-echoOut)說:

VALIDATING PASS foobar 
VALIDATING PASS $2a$10$Q5RYaDrCFFxdXEqYqV4J2OJWHzgOJZJ3wljqVK1jNP4Sqm6ZUOPam 

顯而易見的是,第二驗證失敗。但爲什麼Grails會再次驗證編碼密碼?爲什麼不r.validate()抱怨?第二次驗證發生在哪裏?

我有我做的非常基本的用戶密碼加密錯在這裏的感覺...

首先,我認爲它與Spring Security的領域做添加「accountExpired」等,而不是在約束塊。但是,當我刪除自定義驗證器一切工作正常。

任何幫助表示讚賞:-)

謝謝, 馬特

回答

0

下面是我想是怎麼回事...

  1. 當你調用r.save第二確認發生
  2. beforeInsert方法正在調用encodePassword方法,該方法將PW編碼爲長字符串$ 2a $ 10 $ Q5RYaDrCFFxdXEqYqV4J2OJWHzgOJZJ3wljqVK1jNP4Sqm6ZUOPam
  3. 這是將被驗證並保存在數據庫中的字符串不是'foobar'
  4. 我相信你的正則表達式不允許美元符號,這是導致失敗的編碼字符串的一部分。

我不認爲使用約束條件可以用於你想要做的事情。您需要在編碼之前進行驗證,因此您可能需要在分配PW字段並保存對象之前添加單獨的驗證代碼(在域類或其他地方)並驗證PW。

相關問題