SpringSecurity 過濾器結(jié)構(gòu)整理

SpringSecurity其實(shí)是構(gòu)建了一個過濾器, 對請求進(jìn)行攔截教硫。然后就可以做認(rèn)證、授權(quán)等操作了欺缘。


SecurityBuilder.png

從類名可以看出來栋豫, 這里使用的是建造者模式

  • SecurityBuilder
// 有個范型參數(shù),只有一個build方法, 返回范型
public interface SecurityBuilder<O> {
    O build() throws Exception;
}
  • AbstractSecurityBuilder
public abstract class AbstractSecurityBuilder<O> implements SecurityBuilder<O> {
    private AtomicBoolean building = new AtomicBoolean();
    // 原子布爾類型 保證只會build一次
    public final O build() throws Exception {
        if (this.building.compareAndSet(false, true)) {
            this.object = this.doBuild();
            return this.object;
        } else {
            throw new AlreadyBuiltException("This object has already been built");
        }
    }
    // 子類執(zhí)行真正的構(gòu)建
    protected abstract O doBuild() throws Exception;
}
  • AbstractConfiguredSecurityBuilder抽象類型
public abstract class AbstractConfiguredSecurityBuilder<O, B extends SecurityBuilder<O>> extends AbstractSecurityBuilder<O> {
    // SecurityConfigurer 集合
    private final LinkedHashMap<Class<? extends SecurityConfigurer<O, B>>, List<SecurityConfigurer<O, B>>> configurers;
    private final List<SecurityConfigurer<O, B>> configurersAddedInInitializing;
    private AbstractConfiguredSecurityBuilder.BuildState buildState;
  
    // 建造者模式和模版模式結(jié)合
    protected final O doBuild() throws Exception {
        synchronized(this.configurers) {
            this.buildState = AbstractConfiguredSecurityBuilder.BuildState.INITIALIZING;
            this.beforeInit();
            // 遍歷SecurityConfigurer 集合谚殊, 初始化建造器
            this.init();
            this.buildState = AbstractConfiguredSecurityBuilder.BuildState.CONFIGURING;
            this.beforeConfigure();
            // 遍歷SecurityConfigurer 集合丧鸯, 配置建造器
            this.configure();
            this.buildState = AbstractConfiguredSecurityBuilder.BuildState.BUILDING;
            // 開始建造, 子類實(shí)現(xiàn)
            O result = this.performBuild();
            this.buildState = AbstractConfiguredSecurityBuilder.BuildState.BUILT;
            return result;
        }
    }

    protected abstract O performBuild() throws Exception;

    private void init() throws Exception {
        Collection<SecurityConfigurer<O, B>> configurers = this.getConfigurers();
        Iterator var2 = configurers.iterator();

        SecurityConfigurer configurer;
        while(var2.hasNext()) {
            configurer = (SecurityConfigurer)var2.next();
            configurer.init(this);
        }

        var2 = this.configurersAddedInInitializing.iterator();

        while(var2.hasNext()) {
            configurer = (SecurityConfigurer)var2.next();
            configurer.init(this);
        }

    }

    private void configure() throws Exception {
        Collection<SecurityConfigurer<O, B>> configurers = this.getConfigurers();
        Iterator var2 = configurers.iterator();

        while(var2.hasNext()) {
            SecurityConfigurer<O, B> configurer = (SecurityConfigurer)var2.next();
            configurer.configure(this);
        }

    }
}
  • WebSecurityConfigurerAdapter
// WebSecurity的配置類
@Order(100)
public abstract class WebSecurityConfigurerAdapter implements WebSecurityConfigurer<WebSecurity> {
  public void init(final WebSecurity web) throws Exception {
        // 創(chuàng)建HttpSecurity 并加到SecurityFilterChain的建造列表中
        final HttpSecurity http = this.getHttp();
        web.addSecurityFilterChainBuilder(http).postBuildAction(new Runnable() {
            public void run() {
                FilterSecurityInterceptor securityInterceptor = (FilterSecurityInterceptor)http.getSharedObject(FilterSecurityInterceptor.class);
                web.securityInterceptor(securityInterceptor);
            }
        });
    }

    public void configure(WebSecurity web) throws Exception {
    }
}
  • WebSecurity
public final class WebSecurity extends AbstractConfiguredSecurityBuilder<Filter, WebSecurity> implements SecurityBuilder<Filter>, ApplicationContextAware {
  private final List<SecurityBuilder<? extends SecurityFilterChain>> securityFilterChainBuilders = new ArrayList();
  // 核心就是建造一個Filter出來
  protected Filter performBuild() throws Exception {
        Assert.state(!this.securityFilterChainBuilders.isEmpty(), () -> {
            return "At least one SecurityBuilder<? extends SecurityFilterChain> needs to be specified. Typically this done by adding a @Configuration that extends WebSecurityConfigurerAdapter. More advanced users can invoke " + WebSecurity.class.getSimpleName() + ".addSecurityFilterChainBuilder directly";
        });
        int chainSize = this.ignoredRequests.size() + this.securityFilterChainBuilders.size();
        List<SecurityFilterChain> securityFilterChains = new ArrayList(chainSize);
        Iterator var3 = this.ignoredRequests.iterator();

        while(var3.hasNext()) {
            RequestMatcher ignoredRequest = (RequestMatcher)var3.next();
            securityFilterChains.add(new DefaultSecurityFilterChain(ignoredRequest, new Filter[0]));
        }

        var3 = this.securityFilterChainBuilders.iterator();

        while(var3.hasNext()) {
            SecurityBuilder<? extends SecurityFilterChain> securityFilterChainBuilder = (SecurityBuilder)var3.next();
            // 這里就是HttpSecurity.build()了 
            securityFilterChains.add(securityFilterChainBuilder.build());
        }

        FilterChainProxy filterChainProxy = new FilterChainProxy(securityFilterChains);
        if (this.httpFirewall != null) {
            filterChainProxy.setFirewall(this.httpFirewall);
        }

        filterChainProxy.afterPropertiesSet();
        Filter result = filterChainProxy;
        if (this.debugEnabled) {
            this.logger.warn("\n\n********************************************************************\n**********        Security debugging is enabled.       *************\n**********    This may include sensitive information.  *************\n**********      Do not use in a production system!     *************\n********************************************************************\n\n");
            result = new DebugFilter(filterChainProxy);
        }

        this.postBuildAction.run();
        return (Filter)result;
    }
}
  • HttpSecurity
public final class HttpSecurity extends AbstractConfiguredSecurityBuilder<DefaultSecurityFilterChain, HttpSecurity> implements SecurityBuilder<DefaultSecurityFilterChain>, HttpSecurityBuilder<HttpSecurity> {
  // 核心是建筑DefaultSecurityFilterChain
  protected DefaultSecurityFilterChain performBuild() throws Exception {
        Collections.sort(this.filters, this.comparator);
        return new DefaultSecurityFilterChain(this.requestMatcher, this.filters);
    }
}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末嫩絮,一起剝皮案震驚了整個濱河市丛肢,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌剿干,老刑警劉巖蜂怎,帶你破解...
    沈念sama閱讀 221,198評論 6 514
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異置尔,居然都是意外死亡杠步,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,334評論 3 398
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來幽歼,“玉大人朵锣,你說我怎么就攤上這事〉樗剑” “怎么了诚些?”我有些...
    開封第一講書人閱讀 167,643評論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長皇型。 經(jīng)常有香客問我诬烹,道長,這世上最難降的妖魔是什么弃鸦? 我笑而不...
    開封第一講書人閱讀 59,495評論 1 296
  • 正文 為了忘掉前任绞吁,我火速辦了婚禮,結(jié)果婚禮上寡键,老公的妹妹穿的比我還像新娘掀泳。我一直安慰自己,他們只是感情好西轩,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,502評論 6 397
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著脑沿,像睡著了一般藕畔。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上庄拇,一...
    開封第一講書人閱讀 52,156評論 1 308
  • 那天注服,我揣著相機(jī)與錄音,去河邊找鬼措近。 笑死溶弟,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的瞭郑。 我是一名探鬼主播辜御,決...
    沈念sama閱讀 40,743評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼屈张!你這毒婦竟也來了擒权?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,659評論 0 276
  • 序言:老撾萬榮一對情侶失蹤阁谆,失蹤者是張志新(化名)和其女友劉穎碳抄,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體场绿,經(jīng)...
    沈念sama閱讀 46,200評論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡剖效,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,282評論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片璧尸。...
    茶點(diǎn)故事閱讀 40,424評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡劝贸,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出逗宁,到底是詐尸還是另有隱情映九,我是刑警寧澤,帶...
    沈念sama閱讀 36,107評論 5 349
  • 正文 年R本政府宣布瞎颗,位于F島的核電站件甥,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏哼拔。R本人自食惡果不足惜引有,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,789評論 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望倦逐。 院中可真熱鬧譬正,春花似錦、人聲如沸檬姥。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,264評論 0 23
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽健民。三九已至抒巢,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間秉犹,已是汗流浹背蛉谜。 一陣腳步聲響...
    開封第一講書人閱讀 33,390評論 1 271
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留崇堵,地道東北人型诚。 一個月前我還...
    沈念sama閱讀 48,798評論 3 376
  • 正文 我出身青樓,卻偏偏與公主長得像鸳劳,于是被迫代替她去往敵國和親狰贯。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,435評論 2 359

推薦閱讀更多精彩內(nèi)容

  • Spring Security 是一個能夠?yàn)槠髽I(yè)應(yīng)用系統(tǒng)提供聲明式的安全訪問控制解決方案的安全框架棍辕,減少了為企業(yè)系...
    wch853閱讀 4,118評論 0 11
  • SpringSecurity 初始化流程源碼 本篇主要講解 SpringSecurity初始化流程的源碼部分暮现,包括...
    Aska小強(qiáng)閱讀 951評論 0 1
  • 作者:muggle 前言 由于第一版排版實(shí)在太過糟糕,而且很多細(xì)節(jié)沒交代清楚楚昭,所以決定寫第二版栖袋;這一版爭取將排版設(shè)...
    _muggle閱讀 7,730評論 3 21
  • 核心思想 spring對請求的處理過程如下: 而security所有認(rèn)證邏輯作為特殊的一個Filter加入到spr...
    kar_joe閱讀 2,221評論 0 1
  • 在開發(fā)實(shí)際應(yīng)用項(xiàng)目當(dāng)中,肯定存在用戶登錄和授權(quán)的過程抚太,之前我們使用自己開發(fā)的權(quán)限框架或者 Shiro 來做這塊內(nèi)容...
    breezedancer閱讀 2,751評論 0 51