2013-07-07 44 views
0

我試圖使用spring security acl來驗證用戶的電子郵件地址。我想使用屬於用戶域對象的accountPerson的電子郵件地址。當我保存用戶一切正常,我的數據庫正確更新,但當我嘗試進行身份驗證時,我得到一個hibernate.QueryException: could not resolve property: accountPerson.email of: com.loggyt.User這裏是代碼和錯誤消息。任何幫助將不勝感激。由於grails spring security acl查詢異常

AccountPerson.groovy

class AccountPerson implements Serializable{ 

String firstName 
String lastName 
Address address 
String email 
String primaryPhone 
String secondaryPhone 

static belongsTo = [user:User] 

static mapping = { 
    address cascade: 'all' 
} 

Date dateCreated 
Date lastUpdated 

static constraints = { 
    firstName nullable: false, blank: false 
    lastName nullable: false, blank: false 
    address nullable: true 
    primaryPhone blank: false, nullable: false 
    secondaryPhone blank: true, nullable: true 
    email nullable: false, blank: false, email: true, unique: true 
} 
} 

User.groovy:

import java.util.Date 

class User implements Serializable{ 

transient springSecurityService 

transient String password 

boolean enabled 
boolean accountExpired 
boolean accountLocked 
boolean passwordExpired 

Date dateCreated 
Date lastUpdated 

static hasOne = [accountPerson: AccountPerson] 

static constraints = { 
    password blank: false 
    accountPerson bindable: true 
    password bindable: true 
} 

static mapping = { 
    password column: '`password`' 
    accountPerson fetch: 'join' 
} 

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

void beforeInsert() { 
    encodePassword() 
} 

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

/** 
* After this user has been updated to the database, log the user back in 
* using the new credentials. 
*/ 
void afterUpdate() { 
    this.discard() 
    this.springSecurityService.reauthenticate(person.email) 
} 


/** 
* Get a user based on its email address. 
* 
* @param email email of a user 
* @return the user that has the email parameter 
*/ 
static User findByEmail(String email){ 
    User.createCriteria().get{ 
     accountPerson{ 
      eq('email', email) 
     } 
    } 
} 

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

配置

// Added by the Spring Security Core plugin: 
grails.plugins.springsecurity.userLookup.userDomainClassName = 'com.loggyt.User' 
grails.plugins.springsecurity.userLookup.usernamePropertyName = 'accountPerson.email' 
grails.plugins.springsecurity.userLookup.passwordPropertyName = 'password' 
grails.plugins.springsecurity.userLookup.authorityJoinClassName = 'com.loggyt.UserRole' 
grails.plugins.springsecurity.authority.className = 'com.loggyt.Role' 

自舉

def dbCreate = grailsApplication.config.dataSource.dbCreate 
    if(dbCreate == "create" || dbCreate == "create-drop"){ 

     /** 
     * Create Roles. 
     * 
     */ 
     def adminRole = new Role(authority: 'ROLE_ADMIN').save(flush:true) 
     def userRole = new Role(authority: 'ROLE_USER').save(flush:true) 

     def person = new AccountPerson(
      firstName: 'Otto', 
      lastName: 'Admin', 
      email: "[email protected]", 
      primaryPhone: "555-555-5555") 

     def user = new User (enabled: true, password: "password") 
     user.accountPerson = person 
     user.save(flush:true) 

     UserRole.create user, adminRole, true 

     person = new AccountPerson(
      firstName: 'Normal', 
      lastName: 'User', 
      email: "[email protected]", 
      primaryPhone: "555-555-5555") 

     user = new User (enabled: true, password: "password") 
     user.accountPerson = person 
     user.save(flush:true) 

     UserRole.create user, userRole, true 

     assert User.count() == 2 
     assert Role.count() == 2 
     assert UserRole.count() == 2 
    } 
} 

log4j的調試消息

2013-07-07 00:57:33,088 [http-bio-8443-exec-3] DEBUG authentication.ProviderManager - Authentication attempt using org.springframework.security.authentication.dao.DaoAuthenticationProvider 
2013-07-07 00:57:33,138 [http-bio-8443-exec-3] DEBUG datasource.DataSourceUtils - Fetching JDBC Connection from DataSource 
2013-07-07 00:57:33,162 [http-bio-8443-exec-3] DEBUG support.TransactionTemplate - Initiating transaction rollback on application exception 
Message: could not resolve property: accountPerson.email of: com.loggyt.User; nested exception is org.hibernate.QueryException: could not resolve property: accountPerson.email of: com.loggyt.User 
    Line | Method 
->> 592 | findWhere  in org.grails.datastore.gorm.GormStaticApi 
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
| 686 | withTransaction in  '' 
| 1110 | runWorker . . . in java.util.concurrent.ThreadPoolExecutor 
| 603 | run    in java.util.concurrent.ThreadPoolExecutor$Worker 
^ 722 | run . . . . . . in java.lang.Thread 

Caused by QueryException: could not resolve property: accountPerson.email of: com.loggyt.User 
->> 592 | findWhere  in org.grails.datastore.gorm.GormStaticApi 
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
| 686 | withTransaction in  '' 
| 1110 | runWorker . . . in java.util.concurrent.ThreadPoolExecutor 
| 603 | run    in java.util.concurrent.ThreadPoolExecutor$Worker 
^ 722 | run . . . . . . in java.lang.Thread 

回答

0

我相信默認的UserDetailsS​​ervice查找基於用戶的用戶名,所以除了你已經配置的,你還需要創建一個自定義的UserDetailsS​​ervice並實現loadUserByUsername方法。這裏有一個簡單的例子:

class CustomUserDetailsService implements GrailsUserDetailsService { 

    UserDetails loadUserByUsername(String username, boolean loadRoles) 
throws UsernameNotFoundException { 
    return loadUserByUsername(username) 
    } 

    UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { 

    User.withTransaction { status -> 
     User user = User.findByEmail(username) 

     if (!user) { 
     throw new UsernameNotFoundException('User not found', username) 
     } 

     def authorities = user.authorities.collect { 
     new GrantedAuthorityImpl(it.authority) 
     } 

     return new GrailsUser(user.username, user.password, 
     user.enabled, !user.accountExpired, 
     !user.passwordExpired, !user.accountLocked, 
     authorities ?: NO_ROLES, user.id 
    ) 
    } 
    } 
} 

然後通知的conf /春/ resources.groovy

beans = { 
    userDetailsService(com.loggyt.CustomUserDetailsService) 
} 
+0

真棒新的UserDetailsS​​ervice實現Grails的,這正是我所需要的東西。我在'return new GrailsUser'語句中將'user.username'改爲'user.person.email',它完美地工作,非常感謝你。 – ender

+0

對不起,修改是爲了澄清'user.accountPerson.email'。再次謝謝你。 – ender