spring-security原理與應用系列:建造者

目錄

1.構建過程

AbstractSecurityBuilder

AbstractConfiguredSecurityBuilder

WebSecurity

2.建造者類圖

SecurityBuilder

???????AbstractSecurityBuilder

???????AbstractConfiguredSecurityBuilder

???????WebSecurity

3.小結


? ? ? ? 緊接上一篇文章,這一篇我們來看看構建者WebSecurity是如何構建出一個過濾器對象springSecurityFilterChain的。

1.構建過程

? ? ? ? 點擊類WebSecurityConfiguration的方法springSecurityFilterChain()里的this.webSecurity.build(),如下所示:

AbstractSecurityBuilder

public abstract class AbstractSecurityBuilder<O> implements SecurityBuilder<O> {

... ...

public final O build() throws Exception {
???if (this.building.compareAndSet(false, true)) {
??????this.object = doBuild();
??????return this.object;
???}
???throw new AlreadyBuiltException("This object has already been built");
}

? ? ? ? 在這里,build()方法調用了doBuild()方法。

? ? ? ? 點擊doBuild()方法,如下所示:

???????AbstractConfiguredSecurityBuilder

@Override
protected final O doBuild() throws Exception {
???synchronized (configurers) {
??????buildState = BuildState.INITIALIZING;
??????beforeInit();
??????init();
??????buildState = BuildState.CONFIGURING;
??????beforeConfigure();
??????configure();
??????buildState = BuildState.BUILDING;
??????O result = performBuild();
??????buildState = BuildState.BUILT;
??????return result;
???}
}

? ? ? ? 在這里,定義了構建對象的所有步驟。包括beforeInit、init、beforeConfigure、configure、performBuild的5個步驟。

? ? ? ? 點擊最后一步performBuild,如下所示:

???????WebSecurity

public final class WebSecurity extends
??????AbstractConfiguredSecurityBuilder<Filter, WebSecurity> implements
??????SecurityBuilder<Filter>, ApplicationContextAware {

... ...

@Override
protected Filter performBuild() throws Exception {
???int chainSize = ignoredRequests.size() + securityFilterChainBuilders.size();
???List<SecurityFilterChain> securityFilterChains = new ArrayList<SecurityFilterChain>(
?????????chainSize);
???for (RequestMatcher ignoredRequest : ignoredRequests) {
??????securityFilterChains.add(new DefaultSecurityFilterChain(ignoredRequest));
???}
???for (SecurityBuilder<? extends SecurityFilterChain> securityFilterChainBuilder : securityFilterChainBuilders) {
??????securityFilterChains.add(securityFilterChainBuilder.build());
???}
???FilterChainProxy filterChainProxy = new FilterChainProxy(securityFilterChains);
???if (httpFirewall != null) {
??????filterChainProxy.setFirewall(httpFirewall);
???}
???filterChainProxy.afterPropertiesSet();
???Filter result = filterChainProxy;
???if (debugEnabled) {
??????result = new DebugFilter(filterChainProxy);
???}
???postBuildAction.run();
???return result;
}

? ? ? ? 在這里,可以看到構建的過濾器類是FilterChainProxy。至于這個類的具體結構,我們后續再進行深入的探究。

? ? ? ? 我們先看看在系統運行時,這個FilterChainProxy內部都包含有哪些Filter。

? ? ? ? 設置斷點,如下所示:

???????過濾器代理

? ? ? ? 在這里,我們看到了FilterChainProxy對象內部包含了很多的Filter。后續再深入了解這些Filter的配置過程及應用場景。

? ? ? ? 接下來我們重點學習一下與WebSecurity構建者相關的類圖模型。

2.建造者類圖

? ? ? ?在這里,AbstractSecurityBuilder、AbstractConfiguredSecurityBuilder、WebSecurity都是我們在上面一節中有接觸過的類。

???????SecurityBuilder

? ? ? ? 這個接口是建造者模式的頂級接口,含有建造者對外暴露的構建對象的一個接口方法?build()?。

? ? ? ? 代碼如下:

public interface SecurityBuilder<O> {
???O build() throws Exception;
}

???????AbstractSecurityBuilder

? ? ? ? 這個類是SecurityBuilder接口的抽象子類,實現了接口的build()方法,為確保構建對象只被構建一次,對父接口方法?build()?進行了原子判斷,從而保證每次只構建一次。另外,定義了一個抽象方法?doBuild()?供子類擴展。

? ? ? ? 代碼如下:

public abstract class AbstractSecurityBuilder<O> implements SecurityBuilder<O> {
???private AtomicBoolean building = new AtomicBoolean();
???private O object;
???public final O build() throws Exception {
??????if (this.building.compareAndSet(false, true)) {
?????????this.object = doBuild();
?????????return this.object;
??????}
??????throw new AlreadyBuiltException("This object has already been built");
???}
???public final O getObject() {
??????if (!this.building.get()) {
?????????throw new IllegalStateException("This object has not been built");
??????}
??????return this.object;
???}
???protected abstract O doBuild() throws Exception;
}

???????AbstractConfiguredSecurityBuilder

? ? ? ? 實現父類的doBuild()方法,這里是真正執行構建的地方。

? ? ? ? 首先,使用了建造者模式定義了構建對象的所有步驟;

? ? ? ? 其次,使用了模板方法模式,將構建對象的一些步驟延遲到子類中,使得子類可以不改變該算法結構的情況下重定義該算法的某些特定步驟。

? ? ? ? 代碼如下:

public abstract class AbstractConfiguredSecurityBuilder<O, B extends SecurityBuilder<O>>extends AbstractSecurityBuilder<O> {... ...public <C extends SecurityConfigurer<O, B>> C apply(C configurer) throws Exception {add(configurer);return configurer;}@SuppressWarnings("unchecked")private <C extends SecurityConfigurer<O, B>> void add(C configurer) {Assert.notNull(configurer, "configurer cannot be null");Class<? extends SecurityConfigurer<O, B>> clazz = (Class<? extends SecurityConfigurer<O, B>>) configurer.getClass();synchronized (configurers) {if (buildState.isConfigured()) {throw new IllegalStateException("Cannot apply " + configurer+ " to already built object");}List<SecurityConfigurer<O, B>> configs = allowConfigurersOfSameType ? this.configurers.get(clazz) : null;if (configs == null) {configs = new ArrayList<>(1);}configs.add(configurer);this.configurers.put(clazz, configs);if (buildState.isInitializing()) {this.configurersAddedInInitializing.add(configurer);}}}@Overrideprotected final O doBuild() throws Exception {synchronized (configurers) {buildState = BuildState.INITIALIZING;beforeInit();init();buildState = BuildState.CONFIGURING;beforeConfigure();configure();buildState = BuildState.BUILDING;O result = performBuild();buildState = BuildState.BUILT;return result;}}protected void beforeInit() throws Exception {}protected void beforeConfigure() throws Exception {}protected abstract O performBuild() throws Exception;@SuppressWarnings("unchecked")private void init() throws Exception {Collection<SecurityConfigurer<O, B>> configurers = getConfigurers();for (SecurityConfigurer<O, B> configurer : configurers) {configurer.init((B) this);}for (SecurityConfigurer<O, B> configurer : configurersAddedInInitializing) ?????{configurer.init((B) this);}}@SuppressWarnings("unchecked")private void configure() throws Exception {Collection<SecurityConfigurer<O, B>> configurers = getConfigurers();for (SecurityConfigurer<O, B> configurer : configurers) {configurer.configure((B) this);}}
}

???????WebSecurity

? ? ? ? 實現父類的?performBuild()方法,這是構建對象的所有步驟的最后一個步。通過實現父類方法的方式來定義具體的執行內容。

? ? ? ? WebSecurity?的目標是構建?FilterChainProxy?對象,即構建核心過濾器?springSecurityFilterChain。

? ? ? ? 代碼如下:

public final class WebSecurity extends
??????AbstractConfiguredSecurityBuilder<Filter, WebSecurity> implements
??????SecurityBuilder<Filter>, ApplicationContextAware {
??????... ...
???@Override
???protected Filter performBuild() throws Exception {
??????int chainSize = ignoredRequests.size() + securityFilterChainBuilders.size();
??????List<SecurityFilterChain> securityFilterChains = new ArrayList<>(
????????????chainSize);
??????for (RequestMatcher ignoredRequest : ignoredRequests) {
?????????securityFilterChains.add(new DefaultSecurityFilterChain(ignoredRequest));
??????}
??????for (SecurityBuilder<? extends SecurityFilterChain> securityFilterChainBuilder : securityFilterChainBuilders) {
?????????securityFilterChains.add(securityFilterChainBuilder.build());
??????}
??????FilterChainProxy filterChainProxy = new FilterChainProxy(securityFilterChains);
??????if (httpFirewall != null) {
?????????filterChainProxy.setFirewall(httpFirewall);
??????}
??????filterChainProxy.afterPropertiesSet();

??????Filter result = filterChainProxy;
??????postBuildAction.run();
??????return result;
???}
}

3.小結

? ? ? ? 整個構建過程由beforeInit、init、beforeConfigure、configure、performBuild5大步驟組成。技術層面使用了建造者模式和模板方法模式。


疏漏之處恭請雅正,良策佳議敬候惠示,凡所賜教必當銘感于心。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/74332.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/74332.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/74332.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

OpenHarmony子系統開發 - 電池管理(二)

OpenHarmony子系統開發 - 電池管理&#xff08;二&#xff09; 五、充電限流限壓定制開發指導 概述 簡介 OpenHarmony默認提供了充電限流限壓的特性。在對終端設備進行充電時&#xff0c;由于環境影響&#xff0c;可能會導致電池溫度過高&#xff0c;因此需要對充電電流或電…

xy軸不等比縮放問題——AUTOCAD c#二次開發

在 AutoCAD .net api里&#xff0c;部分實體&#xff0c;像文字、屬性、插入塊等&#xff0c;是不支持非等比縮放的。 如需對AutoCAD中圖形進行xyz方向不等比縮放&#xff0c;則需進行額外的函數封裝。 選擇圖元&#xff0c;指定縮放基準點&#xff0c;scaleX 0.5, scaleY …

如何在 HTML 中創建一個有序列表和無序列表,它們的語義有何不同?

大白話如何在 HTML 中創建一個有序列表和無序列表&#xff0c;它們的語義有何不同&#xff1f; 1. HTML 中有序列表和無序列表的基本概念 在 HTML 里&#xff0c;列表是一種用來組織信息的方式。有序列表就是帶有編號的列表&#xff0c;它可以讓內容按照一定的順序呈現&#…

kafka的文章

1.面試的問題 要點 至多一次、恰好一次數據一致性超時重試、冪等消息順序消息擠壓延時消息 1.1 kafaka 生產消息的過程。 在消息發送的過程中&#xff0c;涉及到了兩個線程&#xff0c;一個是main 線程&#xff0c;一個是sender 線程。在main 線程中創建了一個雙端隊列 Reco…

以mysql 為例,增刪改查語法及其他高級特性

以下是 MySQL 的 增刪改查語法及 高級特性的詳細整理&#xff0c;結合示例說明&#xff1a; 1. 基礎操作&#xff08;CRUD&#xff09; (1) 創建數據&#xff08;INSERT&#xff09; -- 單條插入 INSERT INTO users (id, name, email) VALUES (1, Alice, aliceexample.com);…

Postman最新詳細安裝及使用教程【附安裝包】

一、Postman介紹 ?Postman是一個功能強大的API測試工具&#xff0c;主要用于模擬和測試各種HTTP請求&#xff0c;支持GET、POST、PUT、DELETE等多種請求方法。?通過Postman&#xff0c;用戶可以發送請求并查看返回的響應&#xff0c;檢查響應的內容和狀態&#xff0c;從而驗…

第十三章 : Names in Templates_《C++ Templates》notes

Names in Templates 重難點多選題設計題 重難點 1. 名稱分類與基本概念 知識點&#xff1a; 限定名&#xff08;Qualified Name&#xff09;&#xff1a;使用::或.顯式指定作用域的名稱&#xff08;如std::vector&#xff09;非限定名&#xff08;Unqualified Name&#xff0…

整合vue+Element UI 開發管理系統

1、 安裝 Node.js 和 npm 確保安裝了 Node.js 和 npm。可以通過 Node.js 官網 下載。 2、 創建 Vue 項目 安裝cli npm install -g vue/cli 使用 Vue CLI 創建一個新的 Vue 項目。 vue create admin-system cd admin-system npm run serve 出現這個頁面表示vue創建成功 安…

3. 軸指令(omron 機器自動化控制器)——>MC_Stop

機器自動化控制器——第三章 軸指令 9 MC_Stop變量?輸入變量?輸出變量?輸入輸出變量 功能說明?指令詳情?時序圖?重啟運動指令?多重啟動運動指令?異常 MC_Stop 使軸減速停止。 指令名稱FB/FUN圖形表現ST表現MC_Stop強制停止FBMC_Stop_instance (Axis :《參數》 ,Execu…

C#中修飾符——abstract、virtual

一、多態簡介 在面向對象編程的過程中&#xff0c;多態體現出來的是【一個接口&#xff0c;多個功能】&#xff1b;多態性體現在2個方面&#xff1a; 1、程序運行時&#xff0c;在方法參數、集合或數組等位置&#xff0c;派生類對象可以作為基類的對象處理&#xff1b;這樣該對…

Spring Boot + Spring Integration整合MQTT打造雙向通信客戶端

1. 概述 本文分兩個章節講解MQTT相關的知識&#xff0c;第一部份主要講解MQTT的原理和相關配置&#xff0c;第二個章節主要講和Spring boot的integration相結合代碼的具體實現&#xff0c;如果想快速實現功能&#xff0c;可直接跳過第一章節查看第二章講。 1.1 MQTT搭建 為了…

2025前端面試題記錄

vue項目目錄的執行順序是怎么樣的&#xff1f; 1、package.json   在執行npm run dev時&#xff0c;會在當前目錄尋找package.json文件&#xff0c;此文件包含了項目的名稱版本、項目依賴等相關信息。 2、webpack.config.js(會被vue-cli腳手架隱藏) 3、vue.config.js   對…

專題|Python貝葉斯網絡BN動態推理因果建模:MLE/Bayes、有向無環圖DAG可視化分析呼吸疾病、汽車效能數據2實例合集

原文鏈接&#xff1a;https://tecdat.cn/?p41199 作為數據科學家&#xff0c;我們始終在探索能夠有效處理復雜系統不確定性的建模工具。本專題合集系統性地解構了貝葉斯網絡&#xff08;BN&#xff09;這一概率圖模型在當代數據分析中的創新應用&#xff0c;通過開源工具bnlea…

WX小程序

下載 package com.sky.utils;import com.alibaba.fastjson.JSONObject; import org.apache.http.NameValuePair; import org.apache.http.client.config.RequestConfig; import org.apache.http.client.entity.UrlEncodedFormEntity; import org.apache.http.client.methods.Cl…

Vulnhub-wordpress通關攻略

姿勢一、后臺修改模板拿WebShell 第一步&#xff1a;進?Vulhub靶場并執?以下命令開啟靶場&#xff1b;在瀏覽器中訪問并安裝好.... 第二步&#xff1a;找到外觀--編輯--404.php&#xff0c;將原內容刪除并修改為一句話木馬&#xff0c;點擊更新--File edited successfully. &…

Spring Boot(十六):攔截器Interceptor

攔截器的簡介 攔截器&#xff08;Interceptor&#xff09;?是Spring框架中的概?念&#xff0c;它同樣適?用于Spring Boot&#xff0c;?因為Spring Boot是基于Spring框架的。攔截器是?一種AOP&#xff08;面向切面編程&#xff09;?的輕量級實現方式&#xff0c;它允許我…

Kotlin v2.1.20 發布,標準庫又有哪些變化?

大家吼哇&#xff01;就在三小時前&#xff0c;Kotlin v2.1.20 發布了&#xff0c;更新的內容也已經在官網上更新&#xff1a;What’s new in Kotlin 2.1.20 。 我粗略地看了一下&#xff0c;下面為大家選出一些我比較感興趣、且你可能也會感興趣的內容。 注意&#xff01;這里…

開源鏈動2+1模式、AI智能名片與S2B2C商城小程序源碼在社交電商渠道拓寬中的協同應用研究

摘要&#xff1a;本文基于"開源鏈動21模式""AI智能名片""S2B2C商城小程序源碼"三大技術要素&#xff0c;探討社交電商時代商家渠道拓寬的創新路徑。通過解析各技術的核心機制與應用場景&#xff0c;結合京東便利店等實際案例&#xff0c;論證其對…

【藍橋杯速成】| 10.回溯切割

前面兩篇內容我們都是在做有關回溯問題的組合應用 今天的題目主題是&#xff1a;回溯法在切割問題的應用 題目一&#xff1a;分割回文串 問題描述 131. 分割回文串 - 力扣&#xff08;LeetCode&#xff09; 給你一個字符串 s&#xff0c;請你將 s 分割成一些 子串&#xff…

【嵌入式硬件】三款DCDC調試筆記

關于開關電源芯片&#xff0c;重點關注輸入電源范圍、輸出電流、最低壓降。 1.MP9943: 以MP9943為例&#xff0c;輸入電壓范圍4-36V&#xff0c;輸出最大電流3A&#xff0c;最低壓降為0.3V 調整FB使正常輸出為5.06V 給定6V空載、5V空載、5V帶2A負載的情況&#xff1a; 6V帶2A…