通过Spring SecurityContextHolder更新权限

时间:2015-02-04 01:25:28

标签: java spring spring-mvc spring-security

我正在使用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);

    }
}

1 个答案:

答案 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);

    }
}