Spring Security 整體架構(gòu)操作流程
Spring Security 整體架構(gòu)
前提
開源項(xiàng)目一手文檔基本都在github,標(biāo)準(zhǔn)文檔基本都在官網(wǎng)。
最好的文檔就是官網(wǎng);
在前些年,Apache下還有個(gè)比較流行的權(quán)限框架 Shiro,但是隨著Spring Security (以下簡稱 Security)的流行,逐漸邊緣化。其實(shí)這類框架整體設(shè)計(jì)都大差不差,都是基于一系列的過濾器或者其他攔截手段實(shí)現(xiàn)增強(qiáng)。
整體架構(gòu)
Servlet 整體的過濾器模型

這一塊屬于 Servlet 基礎(chǔ),過濾器算是Servlet核心功能之一,需重點(diǎn)掌握。
Security 過濾器鏈
Security 在 Servlet 過濾器上定義了一個(gè) 自己的過濾器(這個(gè)過濾器使用了委托者設(shè)計(jì)模式)

可以看到,Servlet 過濾器鏈上,不僅有 Security 的過濾器還有 Spring Boot 的一些過濾器,但是這里我們重點(diǎn)關(guān)注圈起來的那個(gè)過濾器(鏈)
再對比官方的這個(gè)圖

就更好理解了。
自定義過濾器
我們自定義的過濾器基本都是在 Security 這個(gè)過濾器鏈上面的,通過編排不同的順序,實(shí)現(xiàn)想要的功能。
在這之前,我們先看看Security默認(rèn)的過濾器鏈上有哪些過濾器官方列表
這里為了照顧,訪問不了官網(wǎng)的,簡單截個(gè)圖。


但不是所有過濾器默認(rèn)都開啟了的。

上面那個(gè)鏈?zhǔn)牵琒pring 全局的過濾器鏈,里面第四個(gè)過濾器委托給了下面那個(gè) Security 的過濾器鏈,在 Security 的過濾器鏈中,可以看到默認(rèn)有14個(gè)過濾器。
其中有幾個(gè)重點(diǎn)關(guān)注的是:
- SecurityContextPersistenceFilter (即將過時(shí),替代者為 SecurityContextHolderFilter),其功能為,支持默認(rèn)的基于 Cookie 的登錄形式;
- 對于新接觸認(rèn)證授權(quán)的開發(fā)者,要明白一點(diǎn),不管什么實(shí)現(xiàn)方案,每一次進(jìn)行鑒權(quán),其本質(zhì)會進(jìn)行一次登錄認(rèn)證,只是方式不同而已LogoutFilter 注銷登錄的過濾器,默認(rèn)的url為 /logout,要實(shí)現(xiàn)自定義退出可以參考
- UsernamePasswordAuthenticationFilter 大部分開發(fā)者,開始接觸 Security 都是模仿這個(gè) 過濾器實(shí)現(xiàn)的自定義登錄
- AnonymousAuthenticationFilter 在 Security 中,認(rèn)證沒有通過或者沒有匹配上認(rèn)證過濾器的請求,最終會被定義為匿名認(rèn)證,這也是一種認(rèn)證結(jié)果,在權(quán)限中也有相關(guān)的配置。
其他的過濾器根據(jù)自己的需求,調(diào)整。
實(shí)際開發(fā)解決方案
在實(shí)際開發(fā)中,目前通常采用前后端分離的形式;有的前端對Cookie 不太友好;因此,為了統(tǒng)一,大部分開發(fā)者會采用 header 認(rèn)證方式。
這樣實(shí)現(xiàn)起碼會有兩個(gè)點(diǎn)需要調(diào)整
1.調(diào)整默認(rèn)認(rèn)證成功的處理方式
默認(rèn)配置下,認(rèn)證成功會跳轉(zhuǎn)到一個(gè)指定的頁面;現(xiàn)在大多會把這個(gè)跳轉(zhuǎn)交給前端。
2.改為header 傳遞認(rèn)證參數(shù)后,默認(rèn)的過濾器就不支持了,需要定義一個(gè) 過濾器,解析header,并進(jìn)行認(rèn)證;個(gè)人推薦將這個(gè)認(rèn)證過濾器放在
AnonymousAuthenticationFilter 的前面,因?yàn)榍懊孢€有些其他認(rèn)證過濾器,如果自定義的過濾器太靠前,可能會被其他認(rèn)證過濾器(比如上面提到的 SecurityContextPersistenceFilter 以及 SecurityContextHolderFilter)給覆蓋掉認(rèn)證信息,當(dāng)然這要取決實(shí)際的優(yōu)先級,萬一你就想自定義的認(rèn)證認(rèn)證過濾器優(yōu)先級低一點(diǎn)呢

可以看到,這兩個(gè)認(rèn)證過濾器不管你是否已經(jīng)認(rèn)證,會直接覆蓋掉認(rèn)證信息。
一個(gè)替代cookie認(rèn)證的filter
提供一個(gè)簡單實(shí)現(xiàn),具體業(yè)務(wù)邏輯,開發(fā)者自己填充
package authorization.filter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.util.StringUtils;
import org.springframework.web.filter.OncePerRequestFilter;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Collections;
public class JwtAuthenticationFilter extends OncePerRequestFilter {
private final Logger logger = LoggerFactory.getLogger(JwtAuthenticationFilter.class);
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
String token = request.getHeader("token");
if (!StringUtils.hasText(token)) {
filterChain.doFilter(request, response);
return;
}
try {
UsernamePasswordAuthenticationToken authenticationToken
= UsernamePasswordAuthenticationToken.authenticated("zhangsan", "zs", Collections.emptyList());
SecurityContext context = SecurityContextHolder.createEmptyContext();
context.setAuthentication(authenticationToken);
SecurityContextHolder.setContext(context);
filterChain.doFilter(request, response);
}
finally {
SecurityContextHolder.clearContext();
}
}
@Override
protected boolean shouldNotFilterErrorDispatch() {
return true;
}
}其他組件,后續(xù)抽時(shí)間再整理整理
到此這篇關(guān)于Spring Security 整體架構(gòu)的文章就介紹到這了,更多相關(guān)Spring Security 整體架構(gòu)內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Java項(xiàng)目五種創(chuàng)建方式示例總結(jié)
這篇文章主要介紹了Java項(xiàng)目五種創(chuàng)建方式的相關(guān)資料,包括普通Java項(xiàng)目、JavaWeb項(xiàng)目(Servlet/JSP)、Maven項(xiàng)目、MavenWeb項(xiàng)目和SpringBoot項(xiàng)目,每種項(xiàng)目類型都有其特定的用途、典型目錄結(jié)構(gòu)、如何創(chuàng)建項(xiàng)目、核心配置、依賴管理和優(yōu)缺點(diǎn),需要的朋友可以參考下2026-01-01
Java線程基本使用之如何實(shí)現(xiàn)Runnable接口
這篇文章主要介紹了Java線程基本使用之如何實(shí)現(xiàn)Runnable接口問題,具有很好的參考價(jià)值,希望對大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-01-01
spring mvc 組合mybatis框架實(shí)例詳解
本項(xiàng)目采用 maven 結(jié)構(gòu),主要演示了 spring mvc + mybatis,controller 獲取數(shù)據(jù)后以json 格式返回?cái)?shù)據(jù)。對spring mvc 組合mybatis的方法感興趣的朋友可以參考下本文2018-01-01

