我正在使用spring-security框架。当我更新权限时,它不会立即生效。我必须退出当前用户(意味着注销),然后重新访问(意味着登录)将更新用户的权限.
是一种在spring security中更新用户权限后立即启用权限的方法吗?
我正在使用spring-security框架。当我更新权限时,它不会立即生效。我必须退出当前用户(意味着注销),然后重新访问(意味着登录)将更新用户的权限.
是一种在spring security中更新用户权限后立即启用权限的方法吗?
您可以 像这样在AbstractSecurityInterceptor中设置 alwaysReauthenticate
<bean id="filterSecurityInterceptor" class="org.springframework.security.web.access.intercept.FilterSecurityInterceptor">
<property name="alwaysReauthenticate" value="true"/>
...
</bean>
当然你应该注意,因为 99,9% 你不需要重新认证。由于身份验证可能使用数据库或其他东西,您的性能可能会降低。但是通常你有一个缓存,比如带有休眠的 2nd Level,所以每次加载 userdetails 应该是在所有权限没有改变的情况下只进行内存操作。
Gandalf 解决方案有效但不完整。为了让 Spring Security 考虑新权限(例如,允许访问以前不可用的页面),您需要创建一个包含新权限列表的新身份验证对象(例如,新 UsernamePasswordAuthenticationToken)。
重置线程本地上下文是不够的,您还需要更新会话:
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 中,会话不是引用,并且通过修改本地线程不会自动更新,您必须手动 session.set 您的对象。
由于您没有在问题中提供确切的详细信息,我假设您有以下情况:
如果是这样,那么您所看到的就是设计使然 - Spring Security 仅在用户第一次尝试登录时为其加载 UserDetails,然后从那时起将其存储在 Session 中。通常这是有道理的,因为它避免了应用程序必须对每个请求执行有关用户详细信息的相同查询。此外,用户的权限在 99.9% 的访问中通常不会发生变化。
要更改此行为,您可能需要考虑在某处添加“刷新”命令/页面,该命令/页面将触发一些代码(您必须编写),这些代码将重新查询 UserDetailsService 并替换 SecurityContext 中的 UserDetails。我不相信有任何内置的方法可以做到这一点。
您可以创建自己的 UserDetails 接口实现,该接口从您的身份验证机制返回,允许访问 GrantedAuthorities[]。然后将您的新权限直接添加到该 UserDetails 对象。如果用户可以同时打开多个会话(或者如果多个用户共享相同的通用登录名),您可能会遇到问题,新权限只会在您更改的会话上看到。
你可以试试这个
SecurityContextHolder.getContext().setAuthentication(SecurityContextHolder.getContext().getAuthentication());