25

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

是一种在spring security中更新用户权限后立即启用权限的方法吗?

4

7 回答 7

9

您可以 像这样在AbstractSecurityInterceptor中设置 alwaysReauthenticate

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

当然你应该注意,因为 99,9% 你不需要重新认证。由于身份验证可能使用数据库或其他东西,您的性能可能会降低。但是通常你有一个缓存,比如带有休眠的 2nd Level,所以每次加载 userdetails 应该是在所有权限没有改变的情况下只进行内存操作。

于 2011-05-18T07:57:07.423 回答
4

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

于 2010-11-06T19:45:56.683 回答
3

以下线程解释了如何在每个请求中重新加载您的用户/主体:

Spring Security 中的每个请求都从数据库中重新加载 UserDetails 对象


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

于 2016-01-25T17:32:54.330 回答
2

重置线程本地上下文是不够的,您还需要更新会话:

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

于 2012-08-02T18:43:35.233 回答
1

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

  1. 您正在提供 UserDetailsS​​ervice 以在用户尝试登录时加载 UserDetails
  2. 作为该服务的一部分,您正在查询数据库/DAO 以加载有关用户权限的详细信息,并基于此设置授予的权限
  3. 当您说“当我更新权限时”时,您指的是更新用户在数据库中的权限(或您存储数据的任何内容)。

如果是这样,那么您所看到的就是设计使然 - Spring Security 仅在用户第一次尝试登录时为其加载 UserDetails,然后从那时起将其存储在 Session 中。通常这是有道理的,因为它避免了应用程序必须对每个请求执行有关用户详细信息的相同查询。此外,用户的权限在 99.9% 的访问中通常不会发生变化。

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

于 2009-05-21T12:49:11.400 回答
0

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

于 2009-05-26T23:54:25.443 回答
-3

你可以试试这个

SecurityContextHolder.getContext().setAuthentication(SecurityContextHolder.getContext().getAuthentication());
于 2011-12-29T10:39:41.643 回答