[英]Update authorities through Spring SecurityContextHolder
我正在使用Spring Security来验证用户身份。
问题是动态更新权限的最佳方法是什么? 我想根据请求更新它,现在我仅在用户登录系统后执行一次。
我有基于经理的应用程序,因此管理员可以决定用户可以做什么,并删除/添加角色。 这种方法存在问题,即用户只有在注销并重新登录后才能获得新的权限集。
我知道我可以用
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
List<GrantedAuthority> authorities = Lists.newArrayList();
userDao.getAuthorities(authorities, user);
Authentication newAuth = new UsernamePasswordAuthenticationToken(auth.getPrincipal(), auth.getCredentials(), authorities);
SecurityContextHolder.getContext().setAuthentication(newAuth);
主要问题是什么时候是合适的时机? 框架到达控制器或拦截器之前有一些过滤器链吗? 它有多安全? 线程安全吗?
可以说,如果我将其放在拦截器中,并且在一个请求中更新SecurityContextHolder时又有另一个请求读取它-会发生什么?
只是草稿
public class VerifyAccessInterceptor extends HandlerInterceptorAdapter {
public boolean preHandle(
HttpServletRequest request,
HttpServletResponse response,
Object handler) throws Exception {
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
List<GrantedAuthority> authorities = Lists.newArrayList();
userDao.getAuthorities(authorities, user);
Authentication newAuth = new UsernamePasswordAuthenticationToken(auth.getPrincipal(), auth.getCredentials(), authorities);
SecurityContextHolder.getContext().setAuthentication(newAuth);
}
}
如果我错了,请纠正我。
从您的问题显而易见,您希望更改基于请求的Authority
。 理想情况下,管理员将具有一个不同的UI,可以在其中删除/添加权限。 这些更改必须实时反映在任何已登录的用户会话中。
当前,您提供的代码段是唯一的方法。
回答您的问题。
The main question is what would be the right moment to do it?
如果要将其仅应用于登录的用户,则必须将其放在拦截器中,因为它将仅在Spring安全过滤器链之后应用。
Some filter chain before framework hit controller or interceptor?
是的,在您的请求到达控制器或拦截器之前,将首先调用DelegatingFilterProxy和FilterChainProxy。
And how safe it is? Thread safe?
是的,如果将SecurityContextHolder
与默认设置一起使用,它将使用线程安全的ThreadLocalSecurityContextHolderStrategy
。
由于所有请求都必须通过拦截器,因此性能会受到影响。 而且由于您仅需要更改权限才需要更改权限,以便在重新设置Authentication
之前在拦截器中进行检查
public class VerifyAccessInterceptor extends HandlerInterceptorAdapter {
public boolean preHandle(
HttpServletRequest request,
HttpServletResponse response,
Object handler) throws Exception {
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
List<GrantedAuthority> authorities = Lists.newArrayList();
userDao.getAuthorities(authorities, user);
// If contents of auth.getAuthorities() equals authorities then no need to re-set.
Authentication newAuth = new UsernamePasswordAuthenticationToken(auth.getPrincipal(), auth.getCredentials(), authorities);
SecurityContextHolder.getContext().setAuthentication(newAuth);
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.