1. 簡介
Spring Security 是用於安全 Spring 應用程序的標準。它具有管理用户身份驗證的多種功能,包括登錄和註銷。
在本教程中,我們將重點介紹使用 Spring Security 進行手動註銷。
我們假設讀者已經理解了標準的 Spring Security 註銷流程。
2. 基本登出
當用户嘗試登出時,會對當前會話狀態產生以下影響。我們需要通過以下兩個步驟銷燬會話:
- 無效化 HTTP 會話信息。
- 清除 SecurityContext,因為它包含身份驗證信息。
SecurityContextLogoutHandler 執行這兩個操作。
讓我們看看它的實際應用:
@Configuration
public class DefaultLogoutConfiguration {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.logout(logout -> logout
.logoutUrl("/basic/basiclogout")
.addLogoutHandler(new SecurityContextLogoutHandler())
);
return http.build();
}
}
請注意,SecurityContextLogoutHandler 是 Spring Security 默認添加的——我們在這裏展示它以供清晰起見。
3. Cookie 清理 註銷
通常,註銷也需要清除用户的一些或全部 Cookie。
為此,我們可以創建一個 LogoutHandler,該 handler 循環遍歷所有 Cookie 並於註銷時將其過期:
@Configuration
public class AllCookieClearingLogoutConfiguration {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.logout(logout -> logout
.logoutUrl("/cookies/cookielogout")
.addLogoutHandler((request, response, auth) -> {
for (Cookie cookie : request.getCookies()) {
String cookieName = cookie.getName();
Cookie cookieToDelete = new Cookie(cookieName, null);
cookieToDelete.setMaxAge(0);
response.addCookie(cookieToDelete);
}
})
);
return http.build();
}
}
實際上,Spring Security 提供了 CookieClearingLogoutHandler,這是一個用於 Cookie 刪除的就緒式註銷 handler。
4. 清除站點數據 Header 註銷
同樣,我們可以使用特殊的 HTTP 響應頭來實現相同的功能;這裏 清除站點數據 頭部發揮作用。
基本上,清除數據站點 頭部清除與請求網站相關的瀏覽數據(cookie、存儲、緩存):
@Configuration
public class ClearSiteDataHeaderLogoutConfiguration {
private static final 清除站點數據 寫入器. 指令[] 源 =
{CACHE, COOKIES, STORAGE, EXECUTION_CONTEXTS};
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.logout(logout -> logout
.logoutUrl("/csd/csdlogout")
.addLogoutHandler(new HeaderWriterLogoutHandler(new ClearSiteDataHeaderWriter(源)))
);
return http.build();
}
}
然而, 僅清除一種存儲類型可能會導致應用程序狀態損壞。因此,由於 不完整清除,頭部僅在請求安全時才應用。
5. 請求時註銷
類似於地,我們可以使用 HttpServletRequest.logout() 方法來註銷用户。
首先,讓我們添加必要的配置以手動調用 .on the request:
@Configuration
public static class LogoutOnRequestConfiguration {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http.securityMatchers("/request/**")
.authorizeHttpRequests(authz -> authz.anyRequest()
.permitAll())
.logout(logout -> logout.logoutUrl("/request/logout")
.addLogoutHandler((request, response, auth) -> {
try {
request.logout();
} catch (ServletException e) {
logger.error(e.getMessage());
}
}));
return http.build();
}
}
最後,讓我們創建一個測試用例以確認一切都按預期工作:
@Test
public void givenLoggedUserWhenUserLogoutOnRequestThenSessionCleared() throws Exception {
this.mockMvc.perform(post("/request/logout").secure(true)
.with(csrf()))
.andExpect(status().is3xxRedirection())
.andExpect(unauthenticated())
.andReturn();
}
6. 結論
總而言之,Spring Security 提供了許多內置功能來處理身份驗證場景。 熟練掌握如何通過編程方式使用這些功能始終非常實用。