最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(wǎng) 會(huì)員登陸 & 注冊(cè)

Spring Security體系結(jié)構(gòu)

2023-05-31 13:57 作者:啥玩意你再說(shuō)一遍  | 我要投稿

? ?

????閱讀該文章前,你需要了解認(rèn)證與授權(quán)的概念,Spring Security就是方便實(shí)現(xiàn)Web應(yīng)用認(rèn)證與授權(quán)的安全管理框架,除此之外你也需要熟悉Servlet Filter的概念與應(yīng)用。

過(guò)濾器回顧

????Spring Security的Servlet支持基于Servlet過(guò)濾器,因此首先了解過(guò)濾器的作用是有幫助的。下圖顯示了單個(gè)HTTP請(qǐng)求的處理程序的典型分層。

????客戶(hù)端向應(yīng)用程序發(fā)送請(qǐng)求,容器根據(jù)請(qǐng)求URI的路徑創(chuàng)建一個(gè)FilterChain,其中包含F(xiàn)ilter實(shí)例和能夠處理HttpServletRequest的Servlet。在Spring MVC應(yīng)用程序中,Servlet是DispatcherServlet的一個(gè)實(shí)例。一個(gè)Servlet最多只能處理一個(gè)HttpServletRequest和HttpServletResponse。但是,可以使用多個(gè)Filter:

  • 防止下游過(guò)濾器實(shí)例或Servlet被調(diào)用。在這種情況下,F(xiàn)ilter通常會(huì)寫(xiě)入HttpServletResponse。

  • 修改下游過(guò)濾器實(shí)例和Servlet使用的HttpServletRequest或HttpServletResponse。

????Filter的功能來(lái)自于傳遞給它的FilterChain。

????由于Filter只影響下游的Filter實(shí)例和Servlet,因此調(diào)用每個(gè)Filter的順序非常重要。

DelegatingFilterProxy

????Spring提供了一個(gè)名為DelegatingFilterProxy的過(guò)濾器實(shí)現(xiàn),它允許在Servlet容器的生命周期和Spring的ApplicationContext之間架橋。Servlet容器允許使用自己的標(biāo)準(zhǔn)注冊(cè)Filter實(shí)例,但它不知道spring定義的bean。您可以通過(guò)標(biāo)準(zhǔn)Servlet容器機(jī)制注冊(cè)DelegatingFilterProxy,但將所有工作委托給實(shí)現(xiàn)Filter的Spring Bean。

????DelegatingFilterProxy的UML類(lèi)圖可以看出來(lái),該類(lèi)實(shí)現(xiàn)了javax.servlet包下的Filter接口,所以為Servlet容器的實(shí)例。

????下面的圖片展示了DelegatingFilterProxy是如何適應(yīng)Filter實(shí)例和FilterChain的。



????DelegatingFilterProxy從ApplicationContext(WebApplicationContext)中查找Bean Filter0,然后調(diào)用Bean Filter0。下面的清單顯示了DelegatingFilterProxy的偽代碼:

(1)惰性獲取已注冊(cè)為Spring Bean的Filter。對(duì)于DelegatingFilterProxy中的例子,委托是Bean Filter0的一個(gè)實(shí)例。

(2)將工作委托給Spring Bean。

????DelegatingFilterProxy的另一個(gè)好處是,它允許延遲查找Filter bean實(shí)例。這很重要,因?yàn)槿萜餍枰谌萜鲉?dòng)之前注冊(cè)Filter實(shí)例。但是,Spring通常使用ContextLoaderListener來(lái)加載Spring bean,直到需要注冊(cè)Filter實(shí)例之后才會(huì)完成。

FilterChainProxy

????Spring Security的Servlet支持包含在FilterChainProxy中。FilterChainProxy是Spring Security提供的一個(gè)特殊過(guò)濾器,它允許通過(guò)SecurityFilterChain向多個(gè)過(guò)濾器實(shí)例委托。因?yàn)镕ilterChainProxy是一個(gè)Bean,所以它通常被封裝在DelegatingFilterProxy中。

????FilterChainProxy應(yīng)該是在DelegatingFilterProxy的doFilter()方法中調(diào)用,由WebSecurity中的performBuild()方法封裝,performBuild()方法中封裝了SecurityFilterChain接口的實(shí)現(xiàn)過(guò)濾器,SecurityFilterChain為org.springframework.security.web包下的過(guò)濾器,可以理解為spring bean。WebSecurityConfiguration類(lèi)中注冊(cè)名為springSecurityFilterChain的spring bean,返回了WebSecurity bean。

????SecurityFilterChain為一個(gè)接口,該接口的實(shí)現(xiàn)類(lèi)只有一個(gè)不可變類(lèi)DefaultSecurityFilterChain,該類(lèi)的成員屬性private final List<Filter> filters中中封裝了真實(shí)的servlet過(guò)濾器。

????下圖顯示了FilterChainProxy的角色。

SecurityFilterChain

????FilterChainProxy使用SecurityFilterChain來(lái)確定應(yīng)該為當(dāng)前請(qǐng)求調(diào)用哪個(gè)Spring SecurityFilter實(shí)例。

????自定義過(guò)濾器并添加到過(guò)濾器鏈中需要自定義配置類(lèi)繼承WebSecurityConfigurerAdapter抽象類(lèi),重寫(xiě)configure(HttpSecurity http)方法,通過(guò)調(diào)用該方法參數(shù)HttpSecurity實(shí)例的addFilterBefore()方法,將自定義過(guò)濾器添加到指定位置。HttpSecurity支持三種filter添加策略:

????HttpSecurity實(shí)例的performBuild()方法構(gòu)造真正的過(guò)濾器鏈,先排序再構(gòu)造過(guò)濾器鏈。HttpSecurity的performBuild()方法在Spring Security應(yīng)用程序啟動(dòng)過(guò)程中執(zhí)行,用于構(gòu)建和配置SecurityFilterChain。

????Spring Security應(yīng)用程序啟動(dòng)過(guò)程中,是由Spring容器管理的。Spring Security核心模塊會(huì)提供一個(gè)名為springSecurityFilterChain的Filter實(shí)例(上文提到過(guò)WebSecurity)。在Spring Security應(yīng)用程序啟動(dòng)時(shí),Spring容器會(huì)對(duì)所有bean進(jìn)行實(shí)例化和初始化工作,會(huì)執(zhí)行通過(guò)@EnableWebSecurity注釋的spring bean,使用該注釋的配置類(lèi)為繼承WebSecurityConfigurerAdapter抽象類(lèi),執(zhí)行該抽象類(lèi)的init()方法,init()方法調(diào)用final HttpSecurity http = getHttp()方法,該方法返回了一個(gè)HttpSecurity實(shí)例。在調(diào)用該實(shí)例的其他方法之前,會(huì)隱式地調(diào)用 performBuild() 方法以構(gòu)建和啟用 SecurityFilterChain。下面是一個(gè)示例 WebSecurityConfigurerAdapter 子類(lèi)中的 configure(HttpSecurity http) 方法的實(shí)現(xiàn),以說(shuō)明 performBuild() 的執(zhí)行時(shí)機(jī):

????在上述代碼中,configure(HttpSecurity http) 方法會(huì)在 Spring Security 啟動(dòng)期間調(diào)用,并傳入一個(gè) HttpSecurity 實(shí)例。該方法通過(guò) http 對(duì)象調(diào)用一系列方法來(lái)配置安全策略,如 authorizeRequests()、formLogin()、logout() 等。在調(diào)用其他方法之前,performBuild() 方法會(huì)自動(dòng)調(diào)用以構(gòu)建和啟用 SecurityFilterChain。

????具體實(shí)現(xiàn)步驟為:

????自定義一個(gè)過(guò)濾器debug如下圖所示:

????SecurityFilterChain 其實(shí)就是我們平時(shí)所說(shuō)的 Spring Security 中的過(guò)濾器鏈,它里邊定義了兩個(gè)方法,一個(gè)是 matches 方法用來(lái)匹配請(qǐng)求,另外一個(gè) getFilters 方法返回一個(gè) List 集合,集合中放著 Filter 對(duì)象,當(dāng)一個(gè)請(qǐng)求到來(lái)時(shí),用 matches 方法去比較請(qǐng)求是否和當(dāng)前鏈吻合,如果吻合,就返回 getFilters 方法中的過(guò)濾器,那么當(dāng)前請(qǐng)求會(huì)逐個(gè)經(jīng)過(guò) List 集合中的過(guò)濾器。

????SecurityFilterChain 接口只有一個(gè)實(shí)現(xiàn)類(lèi),那就是 DefaultSecurityFilterChain。DefaultSecurityFilterChain 其實(shí)就相當(dāng)于是 Spring Security 中的過(guò)濾器鏈,一個(gè) DefaultSecurityFilterChain 代表一個(gè)過(guò)濾器鏈,如果系統(tǒng)中存在多個(gè)過(guò)濾器鏈,則會(huì)存在多個(gè) DefaultSecurityFilterChain 對(duì)象。

????下圖顯示了SecurityFilterChain的角色。


????SecurityFilterChain中的安全過(guò)濾器通常是bean,但它們是在FilterChainProxy而不是DelegatingFilterProxy中注冊(cè)的。FilterChainProxy為直接向Servlet容器或DelegatingFilterProxy注冊(cè)提供了許多優(yōu)點(diǎn)。首先,它為Spring Security的所有Servlet支持提供了一個(gè)起點(diǎn)。因此,如果您試圖對(duì)Spring Security的Servlet支持進(jìn)行故障排除,那么在FilterChainProxy中添加一個(gè)調(diào)試點(diǎn)是一個(gè)很好的開(kāi)始。

????其次,由于FilterChainProxy是Spring Security使用的核心,它可以執(zhí)行非可選的任務(wù)。例如,它清除SecurityContext以避免內(nèi)存泄漏。它還應(yīng)用Spring Security的HttpFirewall來(lái)保護(hù)應(yīng)用程序免受某些類(lèi)型的攻擊。

????此外,它在確定何時(shí)調(diào)用SecurityFilterChain方面提供了更大的靈活性。在Servlet容器中,僅根據(jù)URL調(diào)用Filter實(shí)例。然而,F(xiàn)ilterChainProxy可以通過(guò)使用RequestMatcher接口,基于HttpServletRequest中的任何內(nèi)容來(lái)確定調(diào)用。

????下圖顯示了多個(gè)SecurityFilterChain實(shí)例:

????在Multiple SecurityFilterChain圖中,F(xiàn)ilterChainProxy決定應(yīng)該使用哪個(gè)SecurityFilterChain。只調(diào)用第一個(gè)匹配的SecurityFilterChain。如果請(qǐng)求/api/messages/的URL,它首先匹配/api/**的SecurityFilterChain0模式,因此只調(diào)用SecurityFilterChain0,即使它也匹配SecurityFilterChainn。如果請(qǐng)求/messages/的URL,它與/api/**的SecurityFilterChain0模式不匹配,因此FilterChainProxy繼續(xù)嘗試每個(gè)SecurityFilterChain。假設(shè)沒(méi)有其他SecurityFilterChain實(shí)例匹配,則調(diào)用SecurityFilterChain。

????注意,SecurityFilterChain0只配置了三個(gè)安全過(guò)濾器實(shí)例。然而,securityfilterchain配置了四個(gè)安全過(guò)濾器實(shí)例。需要注意的是,每個(gè)SecurityFilterChain都可以是唯一的,并且可以單獨(dú)配置。事實(shí)上,如果應(yīng)用程序希望Spring security忽略某些請(qǐng)求,SecurityFilterChain可能沒(méi)有安全過(guò)濾器實(shí)例。

Security Filters

????使用SecurityFilterChain API將安全過(guò)濾器插入到FilterChainProxy中。Filter實(shí)例的順序很重要。通常不需要知道Spring Security的Filter實(shí)例的順序。然而,有時(shí)知道順序是有益的。

以下是Spring安全過(guò)濾器排序的綜合列表:

  • ForceEagerSessionCreationFilter

  • ChannelProcessingFilter

  • WebAsyncManagerIntegrationFilter

  • SecurityContextPersistenceFilter

  • HeaderWriterFilter

  • CorsFilter

  • CsrfFilter

  • LogoutFilter

  • OAuth2AuthorizationRequestRedirectFilter

  • Saml2WebSsoAuthenticationRequestFilter

  • X509AuthenticationFilter

  • AbstractPreAuthenticatedProcessingFilter

  • CasAuthenticationFilter

  • OAuth2LoginAuthenticationFilter

  • Saml2WebSsoAuthenticationFilter

  • UsernamePasswordAuthenticationFilter

  • DefaultLoginPageGeneratingFilter

  • DefaultLogoutPageGeneratingFilter

  • ConcurrentSessionFilter

  • DigestAuthenticationFilter

  • BearerTokenAuthenticationFilter

  • BasicAuthenticationFilter

  • RequestCacheAwareFilter

  • SecurityContextHolderAwareRequestFilter

  • JaasApiIntegrationFilter

  • RememberMeAuthenticationFilter

  • AnonymousAuthenticationFilter

  • OAuth2AuthorizationCodeGrantFilter

  • SessionManagementFilter

  • ExceptionTranslationFilter

  • AuthorizationFilter

  • SwitchUserFilter

中途總結(jié)

FilterChainProxy的創(chuàng)建過(guò)程

  1. WebSecurity用來(lái)創(chuàng)建FilterChainProxy過(guò)濾器

    框架用法是寫(xiě)一個(gè)自定義配置類(lèi),繼承WebSecurityConfigurerAdapter,重寫(xiě)幾個(gè)configure()方法

    WebSecurityConfigurerAdapter就是Web安全配置器的適配器對(duì)象

  2. HttpSecurity用來(lái)創(chuàng)建過(guò)濾器鏈的每個(gè)元素

過(guò)濾器鏈加載過(guò)程

  1. SecurityFilterAutoConfiguration類(lèi)會(huì)加載 DelegatingFilterProxyRegistrationBean注冊(cè)過(guò)濾器,名字為springSecurityFilterChain

  2. DelegatingFilterProxy過(guò)濾器根據(jù)名稱(chēng)springSecurityFilterChain獲得FilterChainProxy過(guò)濾器

  3. FilterChainProxy過(guò)濾器doFilter方法執(zhí)行過(guò)濾器,getFilters方法獲得15個(gè)過(guò)濾器

  4. getFilters方法返回值不為空,創(chuàng)建虛擬過(guò)濾器鏈VirtualFilterChain執(zhí)行過(guò)濾器

Handling Security Exceptions

????ExceptionTranslationFilter允許將AccessDeniedException和AuthenticationException轉(zhuǎn)換為HTTP響應(yīng)。

????ExceptionTranslationFilter作為安全過(guò)濾器之一插入到FilterChainProxy中。

????下圖顯示了ExceptionTranslationFilter與其他組件的關(guān)系:

(1)首先,ExceptionTranslationFilter調(diào)用FilterChain。doFilter(request, response)來(lái)調(diào)用應(yīng)用程序的其余部分。

(2)如果用戶(hù)未經(jīng)過(guò)身份驗(yàn)證或者是AuthenticationException,則啟動(dòng)身份驗(yàn)證。

  • 清除SecurityContextHolder

  • 保存HttpServletRequest,以便在身份驗(yàn)證成功后可以使用它重播原始請(qǐng)求

  • AuthenticationEntryPoint用于從客戶(hù)端請(qǐng)求憑據(jù)。例如,它可能重定向到登錄頁(yè)面或發(fā)送WWW-Authenticate標(biāo)頭

(3)否則,如果是AccessDeniedException,則AccessDenied。調(diào)用AccessDeniedHandler來(lái)處理拒絕訪問(wèn)。

注意:如果應(yīng)用程序沒(méi)有拋出AccessDeniedException或AuthenticationException,則ExceptionTranslationFilter不做任何事情。

ExceptionTranslationFilter的偽代碼看起來(lái)像這樣:

(1)如過(guò)濾器回顧中所述,調(diào)用FilterChain。doFilter(request, response)相當(dāng)于調(diào)用應(yīng)用程序的其余部分。這意味著如果應(yīng)用程序的另一部分(FilterSecurityInterceptor或方法security)拋出AuthenticationException或AccessDeniedException,它將被捕獲并在這里處理。

(2)如果用戶(hù)未經(jīng)過(guò)身份驗(yàn)證或者是AuthenticationException,則啟動(dòng)身份驗(yàn)證。

(3)否則,拒絕訪問(wèn)。

Saving Requests Between Authentication

????如處理安全異常中所示,當(dāng)請(qǐng)求沒(méi)有身份驗(yàn)證并且是針對(duì)需要身份驗(yàn)證的資源時(shí),需要保存已驗(yàn)證資源的請(qǐng)求,以便在身份驗(yàn)證成功后重新請(qǐng)求。在Spring Security中,這是通過(guò)使用RequestCache實(shí)現(xiàn)保存HttpServletRequest來(lái)完成的。

RequestCache

????HttpServletRequest保存在RequestCache中。當(dāng)用戶(hù)成功通過(guò)身份驗(yàn)證時(shí),將使用RequestCache重播原始請(qǐng)求。RequestCacheAwareFilter使用RequestCache來(lái)保存HttpServletRequest。

????默認(rèn)情況下,使用HttpeSsionRequestCache。下面的代碼演示了如何定制RequestCache實(shí)現(xiàn),該實(shí)現(xiàn)用于在參數(shù)continue存在的情況下檢查保存請(qǐng)求的HttpSession。

Prevent the Request From Being Saved

????不希望在會(huì)話中存儲(chǔ)用戶(hù)未經(jīng)身份驗(yàn)證的請(qǐng)求的原因有很多。您可能希望將該存儲(chǔ)空間卸載到用戶(hù)的瀏覽器上,或者將其存儲(chǔ)在數(shù)據(jù)庫(kù)中。或者您可能希望關(guān)閉此功能,因?yàn)槟偸窍M麑⒂脩?hù)重定向到主頁(yè),而不是他們?cè)诘卿浨霸噲D訪問(wèn)的頁(yè)面。

????要做到這一點(diǎn),您可以使用NullRequestCache實(shí)現(xiàn)。

RequestCacheAwareFilter

????RequestCacheAwareFilter使用RequestCache來(lái)保存HttpServletRequest。


Spring Security體系結(jié)構(gòu)的評(píng)論 (共 條)

分享到微博請(qǐng)遵守國(guó)家法律
三穗县| 四会市| 荔浦县| 丽江市| 高唐县| 涿州市| 会泽县| 邢台县| 中宁县| 益阳市| 隆子县| 务川| 灵寿县| 于都县| 绥滨县| 环江| 韶关市| 金昌市| 博客| 赤峰市| 陵水| 上犹县| 泾阳县| 嘉祥县| 乐都县| 舟曲县| 平遥县| 连南| 绥德县| 峡江县| 绍兴市| 大悟县| 黔西| 泾川县| 昌乐县| 屏东县| 日土县| 安平县| 湖南省| 波密县| 霸州市|