如何在spring security中更新用户权限后立即启用权限?

时间:2009-05-21 12:40:55

标签: java spring-security

我正在使用spring-security框架。当我更新权限时,它不会立即生效。我必须退出当前用户(意味着注销),然后重新访问(意味着登录)将更新用户的许可。

在spring security中更新用户权限后,是否可以立即启用权限?

7 个答案:

答案 0 :(得分:7)

你可以在你的身上设置alwaysReauthenticate AbstractSecurityInterceptor喜欢这个

<bean id="filterSecurityInterceptor" class="org.springframework.security.web.access.intercept.FilterSecurityInterceptor">
        <property name="alwaysReauthenticate" value="true"/>
 ...
</bean>

当然你应该注意,因为99.9%你不需要重新认证。由于身份验证可能使用数据库或其他内容,因此性能可能会降低。但通常你有一个缓存,比如带有休眠的二级缓存,所以每次加载用户详细信息应该是一个只有内存的操作,在所有情况下权限都没有改变。

答案 1 :(得分:4)

Gandalf解决方案有效但不完整。为了让spring权限被Spring安全性考虑(例如,允许访问以前不可用的页面),您需要创建一个包含新权限列表的新身份验证对象(例如,new UsernamePasswordAuthenticationToken)。

答案 2 :(得分:2)

不足以重置Thread Local上下文,您还需要更新会话:

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你的对象。

答案 3 :(得分:1)

由于您没有在问题中提供确切的详细信息,我认为您的情况如下:

  1. 您正在提供UserDetailsS​​ervice以在用户尝试登录时加载UserDetails
  2. 作为该服务的一部分,您正在查询数据库/ DAO以加载有关用户权限的详细信息,并根据此设置授予的权限
  3. 当您说“我更新权限时”时,您指的是更新用户在数据库中的权限(或者您存储数据的权限)。
  4. 如果是这样,那么您所看到的是设计 - Spring Security仅在用户首次尝试登录时为用户加载UserDetails,然后将其存储在Session中。通常这是有道理的,因为它避免了应用程序必须对每个请求的用户详细信息执行相同的查询。此外,用户的权限通常不会在99.9%的访问中发生变化。

    要更改此行为,您可能需要考虑在某处添加“刷新”命令/页面,这将触发一些代码(您必须编写代码),这将重新查询UserDetailsS​​ervice并替换SecurityContext中的UserDetails。我不相信有任何内置方法可以做到这一点。

答案 4 :(得分:1)

以下主题解释了如何在每次请求时重新加载用户/主体:

Reload UserDetails Object from Database Every Request in Spring Security


完全披露我是上述链接中问题的答案的作者。

答案 5 :(得分:0)

您可以创建自己的身份验证机制返回的UserDetails接口实现,允许访问GrantedAuthorities []。然后将新权限直接添加到该UserDetails对象。如果用户可以同时打开多个会话(或者如果多个用户共享相同的通用登录),则可能会遇到问题,新的权限只会在您更改的会话中看到。

答案 6 :(得分:-2)

你可以试试这个

SecurityContextHolder.getContext().setAuthentication(SecurityContextHolder.getContext().getAuthentication());