今天在grials上安装了Spring Security Core plugin,目的当然是为了实现权限验证。步骤略过不谈。说一下生成的文件。文件如下:
Role.gsp:
class Role {
String authority
static mapping = {
cache true
}
static constraints = {
authority blank: false, unique: true
}
}
User.gps
class User {
transient springSecurityService
String username
String password
boolean enabled
boolean accountExpired
boolean accountLocked
boolean passwordExpired
static constraints = {
username blank: false, unique: true
password blank: false
}
static mapping = {
password column: '`password`'
}
Set<Role> getAuthorities() {
UserRole.findAllByUser(this).collect { it.role } as Set
}
def beforeInsert() {
encodePassword()
}
def beforeUpdate() {
if (isDirty('password')) {
encodePassword()
}
}
protected void encodePassword() {
password = springSecurityService.encodePassword(password)
}
}
UserRole.gsp:
class UserRole implements Serializable {
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) {
find 'from UserRole where user.id=:userId and role.id=:roleId',
[userId: userId, roleId: roleId]
}
static UserRole create(User user, Role role, boolean flush = false) {
new UserRole(user: user, role: role).save(flush: flush, insert: true)
}
static boolean remove(User user, Role role, boolean flush = false) {
UserRole instance = UserRole.findByUserAndRole(user, role)
if (!instance) {
return false
}
instance.delete(flush: flush)
true
}
static void removeAll(User user) {
executeUpdate 'DELETE FROM UserRole WHERE user=:user', [user: user]
}
static void removeAll(Role role) {
executeUpdate 'DELETE FROM UserRole WHERE role=:role', [role: role]
}
static mapping = {
id composite: ['role', 'user']
version false
}
}
从上面三个文件可以看出生成的User和Role没有映射成many-to-many关系。
但是为了实现User和Role的增删改查,尤其是在添加用户时可以通知角色。就需要配置他们的many-to-many关系。然后通过generate-all 生成CRUD的界面。
所以讲User.gsp修改为:
class User {
transient springSecurityService
static hasMany = [roles:Role]
String username
String password
boolean enabled
boolean accountExpired
boolean accountLocked
boolean passwordExpired
static constraints = {
username blank: false, unique: true
password blank: false
}
static mapping = {
password column: '`password`'
roles joinTable: [name: "user_role", key: 'user_id' ]
}
Set<Role> getAuthorities() {
UserRole.findAllByUser(this).collect { it.role } as Set
}
def beforeInsert() {
encodePassword()
}
def beforeUpdate() {
if (isDirty('password')) {
encodePassword()
}
}
protected void encodePassword() {
password = springSecurityService.encodePassword(password)
}
}
Role.gsp修改为:
class Role {
String authority
static hasMany = [users:User]
static belongsTo = wrb.User
static mapping = {
cache true
users joinTable: [name: "user_role", key: 'role_id' ]
}
static constraints = {
authority blank: false, unique: true
}
}
其中红色部分为添加的内容。
之后通过generate-all User 和generate-all Role就可以生成CRUD。并且User的编辑界面可以直接多选其角色。如下图:
发现Roles显示的不是名称。但是查看view目录下的文件发现,调用了role的encodeAsHTML方法。重写Role的encodeAsHTML方法却没有用,估计是final方法,或者是语法糖实现的模板方法。不过重写String toString(){authority}。就可以正常显示了。