Spring-security原始碼-Filter之LogoutFilter(十三)
阿新 • • 發佈:2021-11-10
負責處理登出相關邏輯,預設url對映是/logout
org.springframework.security.config.annotation.web.configurers.LogoutConfigurer 初始化
預設初始化處https://www.cnblogs.com/LQBlog/p/15508248.html#autoid-12-0-0
private void applyDefaultConfiguration(HttpSecurity http) throws Exception { //http本質也是build 這裡都是配置預設的config configure add CsrfConfigurerhttp.csrf(); //預設增加一個WebAsyncManagerIntegrationFilter http.addFilter(new WebAsyncManagerIntegrationFilter()); //configures add ExceptionHandlingConfigurer http.exceptionHandling(); //configures add HeadersConfigurer http.headers(); //configures add SessionManagementConfigurerhttp.sessionManagement(); //configure add SecurityContextConfigurer http.securityContext(); //configure add RequestCacheConfigurer http.requestCache(); ///configure add AnonymousConfigurer http.anonymous(); ///configure add ServletApiConfigurer http.servletApi();//configure DefaultLoginPageConfigurer http.apply(new DefaultLoginPageConfigurer<>()); //configure LogoutConfigurer http.logout(); }
通過http.logout().addLogoutHandler() 可以自定義handler
LogoutFilter
private void doFilter(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException { //匹配是否能夠處理 預設是/logout if (requiresLogout(request, response)) { //從SecurityContextHolder 獲得Authentication資訊 Authentication auth = SecurityContextHolder.getContext().getAuthentication(); if (this.logger.isDebugEnabled()) { this.logger.debug(LogMessage.format("Logging out [%s]", auth)); } /** * 呼叫CompositeLogoutHandler 他也實現了LogoutHandler 他只是一個統一的管理器 * 內部迴圈呼叫LogoutHandler * 預設有三種 * PersistentTokenBasedRememberMeServices <1> * SecurityContextLogoutHandler <2> * LogoutSuccessEventPublishingLogoutHandler<3> */ this.handler.logout(request, response, auth); //處理登出成功的SimpleUrlLogoutSuccessHandler 比如重定向到登入頁 this.logoutSuccessHandler.onLogoutSuccess(request, response, auth); return; } chain.doFilter(request, response); }
<1>
org.springframework.security.web.authentication.rememberme.PersistentTokenBasedRememberMeServices#logout
@Override public void logout(HttpServletRequest request, HttpServletResponse response, Authentication authentication) { //清除cookile super.logout(request, response, authentication); if (authentication != null) { //刪除token this.tokenRepository.removeUserTokens(authentication.getName()); } }
<2>
org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler#logout
@Override public void logout(HttpServletRequest request, HttpServletResponse response, Authentication authentication) { Assert.notNull(request, "HttpServletRequest required"); if (this.invalidateHttpSession) { HttpSession session = request.getSession(false); if (session != null) { //清空session session.invalidate(); if (this.logger.isDebugEnabled()) { this.logger.debug(LogMessage.format("Invalidated session %s", session.getId())); } } } if (this.clearAuthentication) { //清空 SecurityContext context = SecurityContextHolder.getContext(); context.setAuthentication(null); } //清空 SecurityContextHolder.clearContext(); }
<3>
釋出一個spring的事件我們可以監聽這個事件 知道某個使用者登出了 參考:https://www.cnblogs.com/LQBlog/p/13878553.html#_label5
org.springframework.security.web.authentication.logout.LogoutSuccessEventPublishingLogoutHandler#logout
@Override public void logout(HttpServletRequest request, HttpServletResponse response, Authentication authentication) { if (this.eventPublisher == null) { return; } if (authentication == null) { return; } this.eventPublisher.publishEvent(new LogoutSuccessEvent(authentication)); }