好的,因此 Samuel 的帖子中提到的将身份验证与授权分开确实很有帮助。但是仍然有很多陷阱,我发现取消身份验证仍然是必须的,因为在春季没有简单的方法可以向用户添加新角色。所以最简单的方法是强制用户再次登录,让spring在登录时处理角色分配。
为了在 Spring Security 中解除用户身份验证,您必须调用:
SecurityContextHolder.clearContext();
作为替代方案,您可以在 UserDetailsService 实现中抛出异常(见下文)。它的缺点是您会取消用户身份验证并丢失用户上下文数据,因此在创建新本地帐户的过程中无法将新用户帐户与 openid 帐户匹配。并且您必须在用户登录后使用传统的用户名和密码匹配这些帐户。我的解决方案是在创建新帐户后立即取消用户身份验证。
为了授予用户角色(特权),您必须重写 UserDetailsService,以防有人发现这很有用,这是我的实现:
public final class MyUserDetailsService implements UserDetailsService {
private final UsersDao usersDao;
@Autowired
public UserDetailsServiceImpl(final UsersDao usersDao) {
this.usersDao = usersDao;
}
@Override
public UserDetails loadUserByUsername(final String username) {
UserEntity user = usersDao.getUserByOpenIdIdentifier(username);
if (user == null) {
// there is no such user in our db, we could here throw
// an Exception instead then the user would also be deuthenticated
return new User(username, "", new ArrayList<GrantedAuthority>());
}
//here we are granting to users roles based on values from db
final Collection<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>();
authorities.add(new SimpleGrantedAuthority(user.getUserType().toString()));
final UserDetails result = new User(username, "", authorities);
return result;
}
}