对于Spring Security,我需要在AuthenticationSuccessEvent
中注销用户。如果用户使用有效凭据登录,我想根据一些约束来注销用户。
我该怎么做?
@Override
public void onApplicationEvent(AbstractAuthenticationEvent appEvent) {
if (appEvent instanceof AuthenticationSuccessEvent) {
if(Condition true)
{
//LOGOUT
}
}
答案 0 :(得分:1)
我还没有在AuthenticationSuccessEvent
中完成此操作,但尝试的方法是LogoutFilter
做同样的事情。
不幸的是,LogoutFilter
直接在其处理程序方法LogoutFilter.doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
中执行注销处理,因此直接调用它是一种黑客攻击,(但并非不可能)
@Autowired
LogoutFilter logoutFilter;
private void doLogout() {
MockHttpServletRequest request = new MockHttpServletRequest(
"GET",
"http://myApp" + this.logoutFilter.getFilterProcessingUrl());
this.logoutFilter.doFilter(request, new MockHttpServletResponse(),
new MockFilterChain());
}
但这是一个黑客。 - 不管怎样,我会从这开始。它有效,并表明这个概念证明有效,然后我会提出一个更清晰的解决方案:
获取在LogoutHandler
注册的所有LogoutFilter
的列表,然后直接调用它们,然后触发logoutSuccessHandler.onLogoutSuccess
(这正是LogoutFilter所做的)。
@Autowired
List<LogoutHandler> logoutHandlers;
@Autwired
LogoutSuccessHandler logoutSuccessHandler;
private void doLogout() {
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
for (LogoutHandler handler : handlers)
handler.logout(request, response, auth);
logoutSuccessHandler.onLogoutSuccess(request, response, auth);
}
如果您只是想阻止用户因某些限制而无法登录,那么实现界面UserDetailsChecker
并使用AbstractUserDetailsAuthenticationProvider.preAuthenticationChecks
或.postAuthenticationChecks
注册您的实现会更容易和更清晰(您可能使用的DaoAuthenticationProvider
是AbstractUserDetailsAuthenticationProvider
)
(提示:void UserDetailsChecker.check(UserDetails toCheck)
(这是UserDetailsChecker
中唯一的一种方法) - 如果要阻止用户登录,则需要抛出异常。)
private class Demo implements UserDetailsChecker {
public void check(UserDetails user) {
if (!user.isAccountNonLocked())
throw new LockedException("User account is locked");
if (!user.isEnabled())
throw new DisabledException("User is disabled"));
if (!user.isAccountNonExpired())
throw new AccountExpiredException("User account has expired");
//And here comes you!
}
}