在我的 Grails 应用程序中,我使用 Spring Security 插件并定义了 custom userDetailsService Spring bean为了控制如何检索用户和角色数据,例如
class MyUserDetailsService implements GrailsUserDetailsService {
/**
* Some Spring Security classes (e.g. RoleHierarchyVoter) expect at least one role, so
* we give a user with no granted roles this one which gets past that restriction but
* doesn't grant anything.
*/
static final List NO_ROLES = [new GrantedAuthorityImpl(SpringSecurityUtils.NO_ROLE)]
UserDetails loadUserByUsername(String username, boolean loadRoles) {
return loadUserByUsername(username)
}
UserDetails loadUserByUsername(String username) {
User.withTransaction { status ->
User user = User.findByUsername(username)
if (!user) {
throw new UsernameNotFoundException('User not found', username)
}
def authorities = user.authorities.collect {new GrantedAuthorityImpl(it.authority)}
return new CustomUserDetails(
user.username,
user.password,
user.enabled,
!user.accountExpired,
!user.passwordExpired,
!user.accountLocked,
authorities ?: NO_ROLES,
user.id,
user.name)
}
}
}
上面引用的 CustomUserDetails
类只是使用 name
字段扩展 GrailsUser
:
class CustomUserDetails extends GrailsUser {
private static final long serialVersionUID = 1;
final String name
CustomUserDetails(String username,
String password,
boolean enabled,
boolean accountNonExpired,
boolean credentialsNonExpired,
boolean accountNonLocked,
Collection<GrantedAuthority> authorities,
long id,
String displayName) {
super(username, password, enabled, accountNonExpired, credentialsNonExpired, accountNonLocked, authorities, id)
this.name = displayName
}
}
除了自定义用户和角色数据的检索方式之外,我还想控制用户的身份验证方式。就我而言,身份验证过程并不像通常的“检查输入的密码是否与数据库中的密码匹配”那么简单。用户身份验证的实际细节并不相关,因此为了简单起见,我们假设如果用户的 name
字段与输入的密码匹配,则他被授予封装在 中的角色(权限) >自定义用户详细信息
。
我猜想插件中的某处有一个 Spring bean,我可以覆盖它以自定义默认身份验证机制,但是是哪一个呢?由于 name
字段仅由 CustomUserDetails
定义,因此我需要访问 MyUserDetailsService
返回的此类实例才能执行自定义身份验证,这可能吗?
最佳答案
我在这里讨论了自定义登录,示例应用程序的代码为:http://burtbeckwith.com/blog/?p=1090
但是,如果您只想向用户授予与数据库中不同的角色,我会在 MyUserDetailsService
中执行此操作。不要求角色位于数据库中 - Spring Security 只需要一堆 GrantedAuthorityImpl
实例。在我开发的一款应用中,我在身份验证期间自动将 ROLE_USER 授予常规网站用户,以避免浪费数据库空间。
编辑:
如果您使用 DaoAuthenticationProvider,则可以通过自定义 preAuthenticationChecks
和/或 postAuthenticationChecks
bean 在身份验证期间添加其他检查。将插件中的子类化并添加您自己的检查,并将它们在 resources.groovy 中注册为
preAuthenticationChecks(MyPreAuthenticationChecks)
postAuthenticationChecks(MyPostAuthenticationChecks)
关于grails - 在 Spring Security 中自定义身份验证,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20751344/