java 如何在spring security中更新用户权限后立即启用权限?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/892733/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to immediately enable the authority after update user authority in spring security?
提问by Gordian Yuan
I'm using spring-security framework.When I update the permissions,It does not take effect immediately.I have to quit the current user(means logout), and then re-visit(means login) will be to update the user's permission.
我使用的是spring-security框架,当我更新权限时,不会立即生效。我必须退出当前用户(意味着注销),然后重新访问(意味着登录)将更新用户的权限.
Is a way that immediately enable the authority after update user authority in spring security?
是一种在spring security中更新用户权限后立即启用权限的方法吗?
回答by Janning
You can set alwaysReauthenticate in your AbstractSecurityInterceptorlike this
您可以像这样在AbstractSecurityInterceptor 中设置 alwaysReauthenticate
<bean id="filterSecurityInterceptor" class="org.springframework.security.web.access.intercept.FilterSecurityInterceptor">
<property name="alwaysReauthenticate" value="true"/>
...
</bean>
Of course you should pay attention because 99,9% you don't need reauthentication. As authentication might use a database or something else your performance might degrade. But usually you have a cache, like 2nd Level with hibernate, so loading the userdetails everytime should be an memory only operation in all cases where authorities havn't changed.
当然你应该注意,因为 99,9% 你不需要重新认证。由于身份验证可能会使用数据库或其他东西,您的性能可能会降低。但通常你有一个缓存,比如带有休眠的 2nd Level,所以在所有权限没有改变的情况下,每次加载用户详细信息应该是一个仅限内存的操作。
回答by Hyperion
Gandalf solution is valid but not complete. In order for the new permissions to be considered by spring security (eg. allow access to pages previously not available), you need to create a new authentication object (eg. new UsernamePasswordAuthenticationToken) containing the new list of authorities.
甘道夫解决方案有效但不完整。为了让 spring security 考虑新的权限(例如,允许访问以前不可用的页面),您需要创建一个包含新权限列表的新身份验证对象(例如,新的 UsernamePasswordAuthenticationToken)。
回答by Jordi P.S.
Is not enough to reset the Thread Local context, you need to update the session too:
不足以重置 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());
At least in google appengine the session is not a reference and by modifying the thread local doesn't get updated automatically, you have to manually session.set your object.
至少在 google appengine 中,会话不是引用,并且通过修改本地线程不会自动更新,您必须手动 session.set 您的对象。
回答by hooknc
The following thread explains how to reload your user/principal every request:
以下线程解释了如何重新加载您的用户/委托人每个请求:
Reload UserDetails Object from Database Every Request in Spring Security
Spring Security 中的每个请求从数据库重新加载 UserDetails 对象
Full disclosure I am the author of the question and answer of the question in the above link.
完全披露我是上述链接中问题的问答的作者。
回答by matt b
Since you didn't quite provide the exact details in your question, I assume that you have a situation where:
由于您没有在问题中提供确切的细节,我假设您有以下情况:
- You are supplying a UserDetailsService to load up a UserDetails when a user attempts to login
- As a part of that service, you are querying a database/DAO to load up details about a user's permissions, and are setting the granted authorities based on this
- That when you say "When I update the permissions" you are referring to updating the user's permissions in the database (or whatever you are storing data in).
- 您正在提供 UserDetailsService 以在用户尝试登录时加载 UserDetails
- 作为该服务的一部分,您正在查询数据库/DAO 以加载有关用户权限的详细信息,并基于此设置授予的权限
- 当您说“当我更新权限时”时,您指的是更新用户在数据库中的权限(或您存储数据的任何内容)。
If so then what you are seeing is by design - Spring Security only loads the UserDetails for the user the first time, when they attempt to login, and then stores it in Session from then on. Generally this makes sense, as it avoids the application from having to perform the same queries about user details on each request. Also, a user's permissions are generally not changing throughout 99.9% of their visits.
如果是这样,那么您所看到的就是设计 - Spring Security 仅在用户第一次尝试登录时加载 UserDetails,然后从那时起将其存储在 Session 中。通常这是有道理的,因为它避免了应用程序必须对每个请求执行有关用户详细信息的相同查询。此外,用户的权限在他们 99.9% 的访问中通常不会改变。
To change this behavior, you might want to look into adding a "refresh" command/page somewhere that will trigger some code (which you will have to write) which will re-query the UserDetailsService and replace the UserDetails in SecurityContext. I don't believe there is any built-in way to do this.
要更改此行为,您可能需要考虑在某处添加“刷新”命令/页面,以触发一些代码(您必须编写),这些代码将重新查询 UserDetailsService 并替换 SecurityContext 中的 UserDetails。我不相信有任何内置的方法可以做到这一点。
回答by Gandalf
You could create your own implementation of the UserDetails interface that is returned from your authentication mechanism, that allows access to the GrantedAuthorities[]. Then add your new authority directly to that UserDetails object. You may run into issues if a user can have multiple sessions open at once (or if multiple users share the same generic login), that the new permissions will only be seen on the session you have altered.
您可以创建自己的 UserDetails 接口实现,该接口从您的身份验证机制返回,允许访问 GrantedAuthorities[]。然后将您的新权限直接添加到该 UserDetails 对象。如果一个用户可以同时打开多个会话(或者如果多个用户共享同一个通用登录),您可能会遇到问题,即新权限只能在您更改的会话中看到。
回答by yostane
You can try this
你可以试试这个
SecurityContextHolder.getContext().setAuthentication(SecurityContextHolder.getContext().getAuthentication());

