Aur*_*e77 38 java spring spring-security
我正在使用Spring Security通过OpenID进行身份验证的应用程序.当用户登录时,会话中会加载某些权限.
我拥有完全权限的用户,可以修改其他用户的权限(撤销,添加角色).我的问题是,如何动态更改用户会话权限?(不能使用SecurityContextHolder,因为我想更改另一个用户会话).
简单方法:使用户会话无效,但如何?更好的方法:刷新用户会话与新权限,但如何?
leo*_*leo 46
如果您需要动态更新登录用户的权限(当这些权限因任何原因而发生更改时),而无需注销并登录,您只需要Authentication在Spring中重置对象(安全令牌)SecurityContextHolder.
例:
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
List<GrantedAuthority> updatedAuthorities = new ArrayList<>(auth.getAuthorities());
updatedAuthorities.add(...); //add your role here [e.g., new SimpleGrantedAuthority("ROLE_NEW_ROLE")]
Authentication newAuth = new UsernamePasswordAuthenticationToken(auth.getPrincipal(), auth.getCredentials(), updatedAuthorities);
SecurityContextHolder.getContext().setAuthentication(newAuth);
Run Code Online (Sandbox Code Playgroud)
Aur*_*e77 12
谢谢,帮帮我了!有了SessionRegistry,我可以使用getAllPrincipals()来比较要修改的用户与会话中的当前活动用户.如果存在会话,我可以使用以下命令使其会话无效:expireNow()(from SessionInformation)强制重新进行身份验证.
但我不明白它的用处securityContextPersistenceFilter?
编辑:
// user object = User currently updated
// invalidate user session
List<Object> loggedUsers = sessionRegistry.getAllPrincipals();
for (Object principal : loggedUsers) {
if(principal instanceof User) {
final User loggedUser = (User) principal;
if(user.getUsername().equals(loggedUser.getUsername())) {
List<SessionInformation> sessionsInfo = sessionRegistry.getAllSessions(principal, false);
if(null != sessionsInfo && sessionsInfo.size() > 0) {
for (SessionInformation sessionInformation : sessionsInfo) {
LOGGER.info("Exprire now :" + sessionInformation.getSessionId());
sessionInformation.expireNow();
sessionRegistry.removeSessionInformation(sessionInformation.getSessionId());
// User is not forced to re-logging
}
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
Twi*_*wiN 10
如果有人仍在研究如何在不强制该用户重新进行身份验证的情况下更新另一个用户的权限,您可以尝试添加一个重新加载身份验证的拦截器。这将确保您的权限始终处于更新状态。
然而——由于额外的拦截器,将会有一些性能影响(例如,如果你从你的数据库中获取你的用户角色,它将为每个 HTTP 请求查询)。
@Component
public class VerifyAccessInterceptor implements HandlerInterceptor {
// ...
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
Set<GrantedAuthority> authorities = new HashSet<>();
if (auth.isAuthenticated()) {
authorities.add(new SimpleGrantedAuthority("ROLE_USER"));
}
User userFromDatabase = getUserFromDatabase(auth.getName());
if (userFromDatabase != null) {
// add whatever authorities you want here
authorities.add(new SimpleGrantedAuthority("..."));
}
Authentication newAuth = null;
if (auth.getClass() == OAuth2AuthenticationToken.class) {
OAuth2User principal = ((OAuth2AuthenticationToken)auth).getPrincipal();
if (principal != null) {
newAuth = new OAuth2AuthenticationToken(principal, authorities,(((OAuth2AuthenticationToken)auth).getAuthorizedClientRegistrationId()));
}
}
SecurityContextHolder.getContext().setAuthentication(newAuth);
return true;
}
}
Run Code Online (Sandbox Code Playgroud)
此特定实现使用 OAuth2 ( OAuth2AuthenticationToken),但您可以UsernamePasswordAuthenticationToken改用。
现在,将拦截器添加到配置中:
@Configuration
public class WebConfiguration extends WebMvcConfigurationSupport {
@Autowired
private VerifyAccessInterceptor verifyAccessInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(verifyAccessInterceptor).addPathPatterns("/**");
}
}
Run Code Online (Sandbox Code Playgroud)
关键点 - 您应该能够访问用户SecurityContext.
如果你是在servlet环境和使用HttpSession作为securityContextRepository您的securityContextPersistenceFilter,那么就可以使用Spring的完成SessionRegistry.强制用户重新授权(它应该比静默权限撤销更好)使他失效HttpSession.不要忘记添加HttpSessionEventPublisher到web.xml
<listener>
<listener-class>
org.springframework.security.web.session.HttpSessionEventPublisher
</listener-class>
</listener>
Run Code Online (Sandbox Code Playgroud)
如果您使用的是线程本地securityContextRepository,那么您应该添加自定义过滤器springSecurityFilterChain来管理SecurityContexts注册表.为此,您必须使用普通bean springSecurityFilterChain配置(没有security命名空间快捷方式).使用带有自定义过滤器的普通bean配置,您可以完全控制身份验证和授权.
有些链接,它们并不能完全解决您的问题(没有OpenID),但可能有用:
| 归档时间: |
|
| 查看次数: |
32147 次 |
| 最近记录: |