最后我设法解决了这个问题。查询由以下人员生成:
springSecurityService.getCurrentUser()
不幸的是,此方法通过用户名(来自 Principal 对象)获取 User 模型类并将其映射到数据库字段,最多由以下配置:
grails.plugin.springsecurity.userLookup.usernamePropertyName
如上所述in documentation。
我试过了
grails.plugin.springsecurity.userLookup.usernamePropertyName = 'id'
但我收到了从 String 到 Long 的类转换异常。
解决方法很简单 - 创建自己的原则,username 字段类型为 Long。
在我的解决方案中查看PrincipalProxy:
package com.selly.util.security
import java.security.Principal;
import grails.plugin.springsecurity.userdetails.GrailsUser
import org.springframework.security.core.Authentication
import org.springframework.security.core.GrantedAuthority
class AppMetadataAuthenticationToken implements Authentication, Principal {
private boolean authenticated
private GrailsUser userDetails
private Principal principal
public AppMetadataAuthenticationToken(GrailsUser userDetails) {
this.userDetails = userDetails
this.principal = new PrincipalProxy(userDetails)
}
public GrailsUser getUser() {
return userDetails
}
public String getUsername() {
return userDetails.getUsername()
}
@Override
public String getName() {
return userDetails.getUsername()
}
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
return userDetails.getAuthorities()
}
@Override
public Object getCredentials() {
return userDetails.password
}
@Override
public Object getDetails() {
return getUser()
}
@Override
public Object getPrincipal() {
return principal
}
@Override
public boolean isAuthenticated() {
return authenticated
}
@Override
public void setAuthenticated(boolean authenticated) throws IllegalArgumentException {
this.authenticated = authenticated
}
static class PrincipalProxy implements Principal {
GrailsUser grailsUser
Long username
public PrincipalProxy(GrailsUser grailsUser) {
this.grailsUser = grailsUser
this.username = grailsUser.id
}
@Override
public String getName() {
return grailsUser.id
}
}
}
要返回此 Token,只需注册您自己的AuthenticationProvider:
package com.selly.util.security;
import grails.plugin.springsecurity.SpringSecurityService
import org.springframework.security.authentication.AuthenticationProvider
import org.springframework.security.authentication.BadCredentialsException
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken
import org.springframework.security.authentication.dao.DaoAuthenticationProvider
import org.springframework.security.core.Authentication
import org.springframework.security.core.AuthenticationException
import org.springframework.security.core.userdetails.UserDetailsService
import org.springframework.security.core.userdetails.UsernameNotFoundException
public class AppUsernamePasswordAuthenticationProvider extends DaoAuthenticationProvider implements AuthenticationProvider {
SpringSecurityService springSecurityService
@Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
def token = (UsernamePasswordAuthenticationToken) authentication
def user = userDetailsService.loadUserByUsername(authentication.principal)
if(!user)
throw new UsernameNotFoundException("Cannot find user", authentication.principal)
if(!passwordEncoder.isPasswordValid(user.password, authentication.credentials, null))
throw new BadCredentialsException("Invalid password")
return new AppMetadataAuthenticationToken(user)
}
@Override
public boolean supports(Class<?> authentication) {
return UsernamePasswordAuthenticationToken.class.isAssignableFrom(authentication);
}
}
package com.selly.util.security;
import org.springframework.security.authentication.AuthenticationProvider
import org.springframework.security.core.Authentication
import org.springframework.security.core.AuthenticationException
public class AppMetadataAuthenticationProvider implements AuthenticationProvider {
@Override
public Authentication authenticate(Authentication authentication)
throws AuthenticationException {
// TODO Auto-generated method stub
return authentication;
}
@Override
public boolean supports(Class<?> authentication) {
// TODO Auto-generated method stub
return AppMetadataAuthenticationToken.class.isAssignableFrom(authentication);
}
}
在resources.groovy注册
appUsernamePasswordAuthenticationProvider(AppUsernamePasswordAuthenticationProvider) {
userDetailsService = ref('userDetailsService')
passwordEncoder = ref('passwordEncoder')
userCache = ref('userCache')
saltSource = ref('saltSource')
preAuthenticationChecks = ref('preAuthenticationChecks')
postAuthenticationChecks = ref('postAuthenticationChecks')
springSecurityService = ref('springSecurityService')
}
在Config.groovy:
grails.plugin.springsecurity.providerNames = [
'appMetadataAuthenticationProvider',
'appUsernamePasswordAuthenticationProvider',
// 'daoAuthenticationProvider',
// 'anonymousAuthenticationProvider',
// 'rememberMeAuthenticationProvider'
]
现在一切正常:
Hibernate: select this_.id as id13_0_, this_.account_expired as account2_13_0_, this_.account_locked as account3_13_0_, this_.enabled as enabled13_0_, this_."password" as password5_13_0_, this_.password_expired as password6_13_0_, this_.username as username13_0_, this_.workspace as workspace13_0_ from users this_ where (**this_.id=?**) limit ?
除了使用getCurrentUser(),您还可以getPrincipal() 并使用比Principal 接口提供的更多数据强制转换为之前填充的对象。