Grails spring-security-core plugin expects a username column in the role table
I have a really strange problem. I've installed the spring-security-core 1.0.1 in my Grails 1.3.6 application and configured it according to the tutorial - tables are created orderly and populated by BootStrap.groovy. I'm using a PostgreSQL 8.4 database --the whole thing is running on my localhost. Now, the bootstrap works perfectly, but when I try to login I get an exception which says
org.hibernate.exception.SQLGrammarException: could not execute query
and further down:
Caused by: org.postgresql.util.PSQLException: ERROR: Column »username« does not exist
The query that fails is the following:
select
authrole0_.id as id1_,
authrole0_.version as version1_,
authrole0_.authority as authority1_
from
auth_role authrole0_
where
开发者_C百科 username=?
and this is OK, because the auth_role table is not supposed to have username column. But why does Hibernate expect a username column, where it shouldn't be one?
Any clues as how to resolve this?
I've tried two different hibernate diaclects with no effect. I've noticed that the mapping of the table is somehow curious - with the lookup table mapped as well. Unfortunately it says in the documentation of the plugin that I'm not supposed to change it, because the class is needed by the plugin.
My classes look like that:
class AuthUser {
String username
String password
boolean active
boolean accountExpired
boolean accountLocked
boolean passwordExpired
static mapping = {
cache true
username column: '`username`'
password column: '`password`'
}
Set<AuthRole> getAuthorities() {
UserRole.findAllByUser(this).collect { it.role } as Set
}
}
import java.util.Set;
class AuthRole {
String authority
static constraints = {
authority blank: false, unique: true
}
}
import org.apache.commons.lang.builder.HashCodeBuilder
class UserRole implements Serializable {
AuthRole role
AuthUser user
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 (role) builder.append(role.id)
if (user) builder.append(user.id)
builder.toHashCode()
}
static UserRole get(long roleId, long userId) {
find 'from UserRole where role.id=:roleId and user.id=:userId',
[roleId: roleId, userId: userId]
}
static UserRole create(AuthRole role, AuthUser user, boolean flush = false) {
new UserRole(role: role, user: user).save(flush: flush, insert: true)
}
static boolean remove(AuthRole role, AuthUser user, boolean flush = false) {
UserRole instance = UserRole.findByRoleAndUser(role, user)
instance ? instance.delete(flush: flush) : false
}
static void removeAll(AuthRole role) {
executeUpdate 'DELETE FROM UserRole WHERE role=:role', [role: role]
}
static void removeAll(AuthUser user) {
executeUpdate 'DELETE FROM UserRole WHERE user=:user', [user: user]
}
static mapping = {
id composite: ['user', 'role']
version false
}
}
They are pretty much the way the plugin created them.
Thanks, al
OK, found it - "enabled" is a default value. In my class I defined "active" instead of "enabled".
Seems that the plugin is really touchy, when it comes to customizing ;-)
精彩评论