Java 如何在spring security中更新用户权限后立即启用权限?
我正在使用spring security framework。当我更新权限时,它不会立即生效。我必须退出当前用户(意味着注销),然后重新访问(意味着登录)以更新用户的权限Java 如何在spring security中更新用户权限后立即启用权限?,java,spring-security,Java,Spring Security,我正在使用spring security framework。当我更新权限时,它不会立即生效。我必须退出当前用户(意味着注销),然后重新访问(意味着登录)以更新用户的权限 是一种在spring security中更新用户权限后立即启用权限的方法吗?由于您没有在问题中提供确切的细节,我假设您遇到以下情况: 您正在提供UserDetails服务,以便在用户尝试登录时加载UserDetails 作为该服务的一部分,您正在查询数据库/DAO以加载有关用户权限的详细信息,并基于此设置授予的权限 当你说“当
是一种在spring security中更新用户权限后立即启用权限的方法吗?由于您没有在问题中提供确切的细节,我假设您遇到以下情况:
要更改此行为,您可能希望在某个位置添加一个“刷新”命令/页面,该命令/页面将触发一些代码(您必须编写这些代码),这些代码将重新查询UserDetails服务并替换SecurityContext中的UserDetails。我不相信有任何内置方法可以做到这一点。您可以创建自己的UserDetails接口实现,该接口从身份验证机制返回,允许访问授权机构[]。然后将您的新权限直接添加到该UserDetails对象。如果一个用户可以同时打开多个会话(或者如果多个用户共享同一个通用登录名),您可能会遇到问题,即新权限将仅在您更改的会话上显示。Gandalf解决方案有效但不完整。为了让spring security考虑新的权限(例如允许访问以前不可用的页面),您需要创建一个包含新权限列表的新身份验证对象(例如新用户名PasswordAuthenticationToken)。您可以在 像这样
<bean id="filterSecurityInterceptor" class="org.springframework.security.web.access.intercept.FilterSecurityInterceptor">
<property name="alwaysReauthenticate" value="true"/>
...
</bean>
...
当然你应该注意,因为99.9%你不需要重新验证。由于身份验证可能使用数据库或其他东西,您的性能可能会降低。但是通常你有一个缓存,比如hibernate的第二级缓存,所以每次加载userdetails都应该是一个内存操作,在所有权限没有改变的情况下 你可以试试这个
SecurityContextHolder.getContext().setAuthentication(SecurityContextHolder.getContext().getAuthentication());
不足以重置线程本地上下文,您还需要更新会话:
UserContext userContext = (UserContext) context.getAuthentication().getPrincipal();
if (userContext != null && userContext.getUsername() != null) {
//This is my function to refresh the user details
UserDetailsBean userDetails = getUserDetailsBean(userContext.getUsername());
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
if (authentication instanceof UsernamePasswordAuthenticationToken) {
UsernamePasswordAuthenticationToken auth = (UsernamePasswordAuthenticationToken) authentication;
auth.setDetails(userDetails);
}
return userDetails;
} else {
throw new ServiceException("User not authenticated");
}
request.getSession().setAttribute(HttpSessionSecurityContextRepository.SPRING_SECURITY_CONTEXT_KEY, SecurityContextHolder.getContext());
至少在google appengine中,会话不是引用,通过修改线程本地不会自动更新,您必须手动设置会话。设置您的对象。以下线程解释了如何在每个请求中重新加载用户/主体:
完整披露我是上述链接中问题的问答的作者。您的假设是正确的。我想知道有没有什么好方法可以做到这一点而不必重新登录。也许我可以修改存储在当前会话中的用户权限。我正在尝试..如果我想保护bean上的方法,我是否需要对另一个筛选器进行相同的更改,或者这就足够了?据我所知,此筛选器仅适用于web请求。如果您使用的是MEthodSecurityInterceptor,您可以自己调用重新验证。但是,如果每个方法调用之前都检查此web筛选器,因为每个方法调用都在http请求中,那么您应该知道这是正确的答案。我只想补充一点,需要通过节内的
或通过拦截器属性将此拦截器合并到安全配置中:
我尝试了此代码,但不幸的是,它并没有产生任何影响。Spring Source博客上的帖子中描述了一种可能的解决方案。这花了一些时间,但我认为这最终得到了解决: