我正在使用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);
}
}
答案 0 :(得分:0)
如果我错了,请纠正我。
从您的问题来看,很明显您需要基于请求的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);
}
}