Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/307.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 通过Spring SecurityContextHolder更新权限_Java_Spring_Spring Mvc_Spring Security - Fatal编程技术网

Java 通过Spring SecurityContextHolder更新权限

Java 通过Spring SecurityContextHolder更新权限,java,spring,spring-mvc,spring-security,Java,Spring,Spring Mvc,Spring Security,我正在使用Spring安全性对用户进行身份验证 问题是动态更新权限的最佳方式是什么? 我想更新它每一个请求,现在我只做一次后,用户登录到系统 我有一个基于经理的应用程序,所以管理员可以决定用户在任何时候可以做什么,并删除/添加角色。这种方法的问题是,用户只有在注销并重新登录后才能获得新的权限集 我知道我可以用 Authentication auth = SecurityContextHolder.getContext().getAuthentication(); List<GrantedA

我正在使用Spring安全性对用户进行身份验证

问题是动态更新权限的最佳方式是什么? 我想更新它每一个请求,现在我只做一次后,用户登录到系统

我有一个基于经理的应用程序,所以管理员可以决定用户在任何时候可以做什么,并删除/添加角色。这种方法的问题是,用户只有在注销并重新登录后才能获得新的权限集

我知道我可以用

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

    }
}

如果我错了,请纠正我

从您的问题可以明显看出,您希望基于请求的权限更改。理想情况下,管理员将拥有一个不同的UI,可以在其中删除/添加权限。这些更改必须几乎实时地反映在任何登录的用户会话中

目前,您提供的代码段是唯一可以执行此操作的方法

回答你的问题

主要的问题是什么时候做这件事最合适

如果您希望仅将其应用于已登录的用户,则必须将其放在拦截器中,因为它将仅在Spring安全过滤器链之后应用

Some filter chain before framework hit controller or interceptor?
是的,在您的请求到达控制器或拦截器之前,将首先调用DelegatingFilterProxy和FilterChainProxy

And how safe it is? Thread safe?
是的,如果使用带有默认设置的SecurityContextHolder,它将使用线程安全的ThreadLocalSecurityContextHolderStrategy

由于所有请求都必须通过拦截器,因此性能会受到影响。而且,因为只有当权限更改得更好时,才需要更改权限,以便在重新设置身份验证之前在拦截器中检查权限


不需要纠正,你的理解正是我需要的。但仍然有一些东西阻止我在拦截器中这样做,在这个过程中还有其他步骤吗。找到此URL-。谈论AbstractSecurityInterceptor中的AlwaysRecuthenticate,但不确定如何将其与我的代码shippet一起使用。AlwaysRecuthenticate标志用于每次重新登录用户,理想情况下,只需再次调用AuthenticationProvider并在SecurityContextHolder.getContext中设置身份验证。因此,在你的情况下,这不是必需的,因为你只需要重新加载当局。沙津,同意你的观点,但拥有拦截器有多安全?有什么东西阻止我这么做,有没有可能让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);

           // 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);

    }
}