假设您有一个能够禁用用户的正在运行的Web应用程序,我将向您展示如何在运行时锁定那些用户。
基本思想是使用刷新的用户详细信息重新验证每个请求。为此,您将需要一个自定义项
SecurityContextRepository,该自定义项将丢弃保存在http会话中的用户详细信息。
public class RefreshingUserDetailsSecurityContextRepository implements SecurityContextRepository { private final SecurityContextRepository delegate; private final UserDetailsService userDetailsService; public RefreshingUserDetailsSecurityContextRepository(final SecurityContextRepository delegate, final UserDetailsService userDetailsService) { Assert.notNull(delegate); Assert.notNull(userDetailsService); this.delegate = delegate; this.userDetailsService = userDetailsService; } @Override public SecurityContext loadContext(final HttpRequestResponseHolder requestResponseHolder) { SecurityContext securityContext = delegate.loadContext(requestResponseHolder); if(securityContext.getAuthentication() == null) { return securityContext; } Authentication principal = securityContext.getAuthentication(); UserDetails userDetails = userDetailsService.loadUserByUsername(principal.getName()); //this pre has to be modified when using remember me service, jaas or a custom authentication token UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(userDetails, userDetails.getPassword()); securityContext.setAuthentication(token); saveContext(securityContext, requestResponseHolder.getRequest(), requestResponseHolder.getResponse()); return securityContext; } @Override public void saveContext(final SecurityContext context, final HttpServletRequest request, final HttpServletResponse response) { delegate.saveContext(context, request, response); } @Override public boolean containsContext(final HttpServletRequest request) { return delegate.containsContext(request); }}RefreshingUserDetailsSecurityContextRepository只包装默认值
SecurityContextRepository,即
HttpSessionSecurityContextRepository。因此,您无需担心会话超时或
SecurityContext自己存储。在该
loadContext方法中,用户详细信息将刷新并发
userDetailsService回给
SecurityContext发给呼叫者之前。
不要将用户权限传递给
UsernamePasswordAuthenticationToken构造函数。否则,令牌将标记为已认证,并且永远不会触发重新认证!
当心
RefreshingUserDetailsSecurityContextRepository限制了你
UsernamePasswordAuthenticationToken。例如,如果您想使用Jaas,Spring
Security,请记住我或不是源自
UsernamePasswordAuthenticationToken您的自定义身份验证令牌,它需要适应
RefreshingUserDetailsSecurityContextRepository您的需求。
添加
RefreshingUserDetailsSecurityContextRepository到您的安全配置。
<security:http use-expressions="true" security-context-repository-ref="refreshingUserDetailsSecurityContextRepository"> <security:intercept-url ... /> <security:form-login ... /> <security:logout /></security:http><bean id="refreshingUserDetailsSecurityContextRepository" > <constructor-arg index="0"> <bean /> </constructor-arg> <constructor-arg index="1" ref="userDetailsService" /></bean>
而已。已登录但已禁用的用户会在下一页请求中被重定向回登录页面。
这是一个功能齐全的示例。



