向Spring Security用户添加自定义字段

时间:2014-05-29 21:04:38

标签: grails spring-security

使用spring security的s2-quickstart脚本生成User,Role和UserRole类后,我现在想要向用户类添加字段,例如电子邮件。

我的用户类包含:

//User.groovy
String username
String password
String email
boolean enabled = true
boolean accountExpired
boolean accountLocked
boolean passwordExpired

一切似乎都有效,直到我按照文档中的教程执行以下操作

//BootStrap.goovy
def adminRole = new Role(authority:'ROLE_ADMIN').save(flush: true)
def adminUser = new User(username:'admin', password:'password')
adminUser.save(flush: true)
UserRole.create adminUser, adminRole, true

这产生了输出:

|Loading Grails 2.3.8
|Configuring classpath
.
|Environment set to development
.................................
|Packaging Grails application
...........
|Compiling 1 source files
...................................
|Running Grails application
Configuring Spring Security Core ...
... finished configuring Spring Security Core
| Error 2014-05-29 21:59:59,728 [localhost-startStop-1] ERROR context.GrailsContextLoader  - Error initializing the application: No signature of method: uk.co.xonos.bookings.UserRole.exists() is applicable for argument types: (null, java.lang.Long) values: [null, 1]
Possible solutions: exists(long, long), exists(java.io.Serializable), list(), first(), wait(), last()
Message: No signature of method: uk.co.xonos.bookings.UserRole.exists() is applicable for argument types: (null, java.lang.Long) values: [null, 1]
Possible solutions: exists(long, long), exists(java.io.Serializable), list(), first(), wait(), last()
   Line | Method
->>  91 | methodMissing                    in org.grails.datastore.gorm.GormStaticApi
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
|    86 | doCall                           in uk.co.xonos.bookings.UserRole$__clinit__closure9_closure14_closure15
|    85 | doCall . . . . . . . . . . . . . in uk.co.xonos.bookings.UserRole$__clinit__closure9_closure14
|    44 | create                           in uk.co.xonos.bookings.UserRole
|    39 | doCall . . . . . . . . . . . . . in BootStrap$_closure1
|   308 | evaluateEnvironmentSpecificBlock in grails.util.Environment
|   301 | executeForEnvironment . . . . .  in     ''
|   277 | executeForCurrentEnvironment     in     ''
|   303 | innerRun . . . . . . . . . . . . in java.util.concurrent.FutureTask$Sync
|   138 | run                              in java.util.concurrent.FutureTask
|   895 | runTask . . . . . . . . . . . .  in java.util.concurrent.ThreadPoolExecutor$Worker
|   918 | run                              in     ''
^   695 | run . . . . . . . . . . . . . .  in java.lang.Thread
Error |
Forked Grails VM exited with error
|Server running. Browse to http://localhost:8080/Bookings

干杯

==编辑==

根据dmahapatro的要求,这是我的UserRole类,不是从生成的模型中编辑的

package uk.co.xonos.bookings

import org.apache.commons.lang.builder.HashCodeBuilder

class UserRole implements Serializable {

    private static final long serialVersionUID = 1

    User user
    Role role

    boolean equals(other) {
        if (!(other instanceof UserRole)) {
            return false
        }

        other.user?.id == user?.id &&
        other.role?.id == role?.id
    }

    int hashCode() {
        def builder = new HashCodeBuilder()
        if (user) builder.append(user.id)
        if (role) builder.append(role.id)
        builder.toHashCode()
    }

    static UserRole get(long userId, long roleId) {
        UserRole.where {
            user == User.load(userId) &&
            role == Role.load(roleId)
        }.get()
    }

    static boolean exists(long userId, long roleId) {
        UserRole.where {
            user == User.load(userId) &&
            role == Role.load(roleId)
        }.count() > 0
    }

    static UserRole create(User user, Role role, boolean flush = false) {
        def instance = new UserRole(user: user, role: role)
        instance.save(flush: flush, insert: true)
        instance
    }

    static boolean remove(User u, Role r, boolean flush = false) {
        if (u == null || r == null) return false

        int rowCount = UserRole.where {
            user == User.load(u.id) &&
            role == Role.load(r.id)
        }.deleteAll()

        if (flush) { UserRole.withSession { it.flush() } }

        rowCount > 0
    }

    static void removeAll(User u, boolean flush = false) {
        if (u == null) return

        UserRole.where {
            user == User.load(u.id)
        }.deleteAll()

        if (flush) { UserRole.withSession { it.flush() } }
    }

    static void removeAll(Role r, boolean flush = false) {
        if (r == null) return

        UserRole.where {
            role == Role.load(r.id)
        }.deleteAll()

        if (flush) { UserRole.withSession { it.flush() } }
    }

    static constraints = {
        role validator: { Role r, UserRole ur ->
            if (ur.user == null) return
            boolean existing = false
            UserRole.withNewSession {
                existing = UserRole.exists(ur.user.id, r.id)
            }
            if (existing) {
                return 'userRole.exists'
            }
        }
    }

    static mapping = {
        id composite: ['role', 'user']
        version false
    }
}

==编辑2 ==

根据塞尔吉奥·米歇尔斯的要求,完成了他的sugestions后,打印出以下内容:

grails.validation.ValidationErrors: 1 errors
Field error in object 'uk.co.xonos.bookings.User' on field 'email': rejected value [null]; codes [uk.co.xonos.bookings.User.email.nullable.error.uk.co.xonos.bookings.User.email,uk.co.xonos.bookings.User.email.nullable.error.email,uk.co.xonos.bookings.User.email.nullable.error.java.lang.String,uk.co.xonos.bookings.User.email.nullable.error,user.email.nullable.error.uk.co.xonos.bookings.User.email,user.email.nullable.error.email,user.email.nullable.error.java.lang.String,user.email.nullable.error,uk.co.xonos.bookings.User.email.nullable.uk.co.xonos.bookings.User.email,uk.co.xonos.bookings.User.email.nullable.email,uk.co.xonos.bookings.User.email.nullable.java.lang.String,uk.co.xonos.bookings.User.email.nullable,user.email.nullable.uk.co.xonos.bookings.User.email,user.email.nullable.email,user.email.nullable.java.lang.String,user.email.nullable,nullable.uk.co.xonos.bookings.User.email,nullable.email,nullable.java.lang.String,nullable]; arguments [email,class uk.co.xonos.bookings.User]; default message [Property [{0}] of class [{1}] cannot be null]

2 个答案:

答案 0 :(得分:2)

这可能是因为您的用户创建失败了,而您没有验证它。尝试将BootStrap更改为:

def adminRole = new Role(authority:'ROLE_ADMIN')
assert adminRole.save(flush: true)
def adminUser = new User(username:'admin', password:'password')
assert adminUser.save(flush: true)

如果失败,请更改以打印错误:

adminUser.validate()
println adminUser.errors

我的猜测是你没有在验证栏中添加电子邮件,这是强制性的。

答案 1 :(得分:0)

这可能是因为您的域类UserRole包含au属性id。 此id属性用于UserRole。 这是不允许的,因为Grails Spring插件使用了参数名id。 在Grails spring插件中,此参数的类型很长。

解决方案: 将您的媒体资源名称从id更改为uuid。或删除该属性。

例如: def role1 = Role.findOrSaveWhere(authority: 'ROLE_ADMIN') def defaultUser = User.findOrSaveWhere(username: 'admin', password: 'password', ) if(!defaultUser.authorities.contains(role1)){ UserRole.create(defaultUser,role1,true) } 希望有所帮助。