监听AuthenticationSuccessEvent,注意在刷新令牌,校验令牌,登录密码校验成功都会发布这个事件,所以我们需要在监听器里面做一些排查判断。successHandler是自定义业务逻辑类。
public class AuthenticationSuccessEventListener implements ApplicationListener认证失败{ @Autowired(required = false) private AuthenticationSuccessHandler successHandler; @Override public void onApplicationEvent(AuthenticationSuccessEvent event) { Authentication authentication = (Authentication) event.getSource(); // successHandler不为空并且已经是认证用户,从请求上下文中拿到请求属性 if (successHandler != null && isUserAuthentication(authentication)) { ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); HttpServletRequest request = requestAttributes.getRequest(); HttpServletResponse response = requestAttributes.getResponse(); // 调用自定义业务实现 successHandler.handle(authentication, request, response); } } private boolean isUserAuthentication(Authentication authentication) { if (authentication.getPrincipal() instanceof SecurityUser) { return true; } return CollUtil.isNotEmpty(authentication.getAuthorities()); } }
监听AuthenticationFailureBadCredentialsEvent,注意在刷新令牌,校验令牌,登录密码校验成功都会发布这个事件,所以我们需要在监听器里面做一些排查判断。successHandler是自定义业务逻辑类。
public class AuthenticationFailureEventListener implements ApplicationListener退出成功{ @Autowired(required = false) private AuthenticationFailureHandler failureHandler; @Override public void onApplicationEvent(AuthenticationFailureBadCredentialsEvent event) { ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); HttpServletRequest request = requestAttributes.getRequest(); HttpServletResponse response = requestAttributes.getResponse(); AuthenticationException authenticationException = event.getException(); Authentication authentication = (Authentication) event.getSource(); // 调用自定义业务实现 if (failureHandler != null) { failureHandler.handle(authenticationException, authentication, request, response); } } private boolean isUserAuthentication(Authentication authentication) { if (authentication.getPrincipal() instanceof SecurityUser) { return true; } return CollUtil.isNotEmpty(authentication.getAuthorities()); } }
Spring security oauth2.0是没有退出接口的
@RestController
@AllArgsConstructor
@RequestMapping("/token")
public class CustomTokenEndpoint {
private final TokenStore tokenStore;
@DeleteMapping("/logout")
public R logout(@RequestHeader(value = HttpHeaders.AUTHORIZATION, required = false) String authHeader) {
if (StrUtil.isBlank(authHeader)) {
return R.ok(Boolean.FALSE, "退出失败,token 为空");
}
String tokenValue = authHeader.replace(OAuth2AccessToken.BEARER_TYPE, "").trim();
OAuth2AccessToken accessToken = tokenStore.readAccessToken(tokenValue);
if (accessToken == null || StrUtil.isBlank(accessToken.getValue())) {
return R.ok(Boolean.TRUE, "退出失败,token 无效");
}
OAuth2Authentication auth2Authentication = tokenStore.readAuthentication(accessToken);
// 清空用户信息
// 清空access token
tokenStore.removeAccessToken(accessToken);
// 清空 refresh token
OAuth2RefreshToken refreshToken = accessToken.getRefreshToken();
tokenStore.removeRefreshToken(refreshToken);
// 发送退出成功事件
SpringContextHolder.publishEvent(new LogoutSuccessEvent(auth2Authentication));
return R.ok();
}
@GetMapping(value = "/authentication")
public String info() {
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
if (!authentication.isAuthenticated()) {
return null;
}
Object principal = authentication.getPrincipal();
String username = null;
if (principal instanceof UserDetails) {
username = ((UserDetails) principal).getUsername();
} else {
username = principal.toString();
}
return username;
}
}
event
public class LogoutSuccessEvent extends AbstractAuthenticationEvent {
public LogoutSuccessEvent(Authentication authentication) {
super(authentication);
}
}
@Slf4j
public class SpringContextHolder implements ApplicationContextAware, DisposableBean {
private static ApplicationContext applicationContext = null;
public static ApplicationContext getApplicationContext() {
return applicationContext;
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) {
SpringContextHolder.applicationContext = applicationContext;
}
@SuppressWarnings("unchecked")
public static T getBean(String name) {
return (T) applicationContext.getBean(name);
}
public static T getBean(Class requiredType) {
return applicationContext.getBean(requiredType);
}
public static void clearHolder() {
if (log.isDebugEnabled()) {
log.debug("清除SpringContextHolder中的ApplicationContext:" + applicationContext);
}
applicationContext = null;
}
public static void publishEvent(ApplicationEvent event) {
if (applicationContext == null) {
return;
}
applicationContext.publishEvent(event);
}
@Override
public void destroy() {
SpringContextHolder.clearHolder();
}
}
监听器
@Slf4j public class AuthenticationLogoutSuccessEventListener implements ApplicationListener{ @Autowired(required = false) private AuthenticationLogoutHandler logoutHandler; @Override public void onApplicationEvent(LogoutSuccessEvent event) { OAuth2Authentication authentication = (OAuth2Authentication) event.getSource(); // successHandler不为空 并且 已经是认证用户 。从请求上下文中拿到请求属性 if (logoutHandler != null && isUserAuthentication(authentication)) { ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); HttpServletRequest request = requestAttributes.getRequest(); HttpServletResponse response = requestAttributes.getResponse(); // 调用自定义业务实现 logoutHandler.handle(authentication, request, response); } } private boolean isUserAuthentication(Authentication authentication) { if (authentication.getPrincipal() instanceof SecurityUser) { return true; } return CollUtil.isNotEmpty(authentication.getAuthorities()); } }
最后记得加上@Component注解放入Spring容器中



