UserDetails.getAuthorities()
持有当前登录用户的所有角色。因为你已经有一个习惯UserDetails
您只需在getAuthorities()
会话中开始时将附加角色添加到返回的值中,然后在会话中结束时将其删除。(见下面的编辑)
IE:
public class MyUserDetails implements UserDetails {
// holds the authorities granted to the user in DB
private List<GrantedAuthority> authorities;
// holds the temporarily added authorities for the mid-session
private List<GrantedAuthority> extraAuthorities;
public GrantedAuthority[] getAuthorities() {
List<GrantedAuthority> auths = new ArrayList<GrantedAuthority>();
auths.addAll(this.authorities);
auths.addAll(this.extraAuthorities);
return auths;
}
public void addExtraAuthorities(GrantedAuthority...auths) {
for (GrantedAuthority a : auths) {
this.extraAuthorities.add(a);
}
}
public void clearExtraAuthorities() {
this.extraAuthorities.clear();
}
}
或者,您可以围绕原始 UserDetails 创建一个包装器,该包装器将保存额外的权限并将其包装并在会话中期开始时设置为当前的 Authentication 对象,并在会话中期结束时展开。
编辑:
正如本在评论中指出的那样UserDetails.getAuthorities()
,在登录时,当创建对象时,它只被调用一次Authentication
——我忘记了这一点。但这给我们带来了正确的答案,这一次我确信它会起作用,因为我自己就是这样做的。是注意的Authentication.getAuthorities()
方法,而不是UserDetails.getAuthorities()
。我真的推荐一个包装器,而不是交互的自定义实现Authentication
,因为它会更灵活,并允许透明地支持下面的不同身份验证机制。
IE:
public class MidSessionAuthenticationWrapper implements Authentication {
private Authentication wrapped;
private List<GrantedAuthority> authorities;
public MidSessionAuthenticationWrapper(
Authentication wrapped, Collection<GrantedAuthority> extraAuths) {
this.wrapped = wrapped;
this.authorities = new ArrayList<GrantedAuthority>(wrapped.getAuthorities());
this.authorities.addAll(extraAuths);
}
public Authentication getWrapped() {
return this.wrapped;
}
@Override
public Collection<GrantedAuthority> getAuthorities() {
return this.authorities;
}
// delegate all the other methods of Authentication interace to this.wrapped
}
然后你需要做的就是在会话中开始:
Authentication authentication =
SecurityContextHolder.getContext().getAuthentication();
Collection<GrantedAuthority> extraAuths =
null; // calculate the extra authorities
MidSessionAuthenticationWrapper midSessionAuthentication =
new MidSessionAuthenticationWrapper(authentication, extraAuths);
SecurityContextHolder.getContext().setAuthentication(midSessionAuthentication);
在会议中期结束时:
MidSessionAuthenticationWrapper midSessionAuthentication =
(MidSessionAuthenticationWrapper) SecurityContextHolder.getContext().getAuthentication();
Authentication authentication = midSessionAuthentication.getWrapped();
SecurityContextHolder.getContext().setAuthentication(authentication);