您好,登錄后才能下訂單哦!
本篇內(nèi)容介紹了“如何理解Spring Security架構(gòu)”的有關(guān)知識(shí),在實(shí)際案例的操作過(guò)程中,不少人都會(huì)遇到這樣的困境,接下來(lái)就讓小編帶領(lǐng)大家學(xué)習(xí)一下如何處理這些情況吧!希望大家仔細(xì)閱讀,能夠?qū)W有所成!
本指南是Spring Security的入門(mén),它提供了對(duì)該框架的設(shè)計(jì)和基本構(gòu)建的見(jiàn)解。我們僅介紹了應(yīng)用程序安全性的最基本知識(shí),但是這樣做可以解除使用Spring Security的開(kāi)發(fā)人員所遇到的一些困惑。為此,我們會(huì)看一下使用過(guò)濾器(更通常是使用方法注釋?zhuān)┰赪eb應(yīng)用程序中應(yīng)用安全性的方式。當(dāng)你需要從高層次了解安全應(yīng)用程序的工作方式,如何自定義它,或者僅需要學(xué)習(xí)如何考慮應(yīng)用程序安全性時(shí),請(qǐng)使用本指南。
本指南并不是解決最基本問(wèn)題的手冊(cè)(對(duì)于基本問(wèn)題,有很多其他可參考的資料),但對(duì)于初學(xué)者和專(zhuān)家都可能有用。 Spring Boot也被提及了很多次,因?yàn)樗鼮榘踩膽?yīng)用程序提供了一些默認(rèn)行為,并且理解它與整個(gè)體系結(jié)構(gòu)之間的關(guān)系會(huì)對(duì)你很有幫助。所有這些原則同樣適用于不使用Spring Boot的應(yīng)用程序。
應(yīng)用程序安全性差不多可以歸結(jié)為兩個(gè)獨(dú)立的問(wèn)題:身份認(rèn)證(你是誰(shuí))和授權(quán)(authorization)(你可以做什么?)。 有時(shí)人們會(huì)說(shuō)“訪問(wèn)控制”而不是“授權(quán)”,這可能會(huì)造成困惑,但是以這種方式思考可能會(huì)有所幫助,因?yàn)椤笆跈?quán)”在其他地方又有其他含義。 Spring Security的體系結(jié)構(gòu)旨在將身份認(rèn)證與授權(quán)分開(kāi),并且具有許多策略和擴(kuò)展點(diǎn)。
認(rèn)證的主要策略接口是AuthenticationManager
,該接口只有一個(gè)方法:
public interface AuthenticationManager { Authentication authenticate(Authentication authentication) throws AuthenticationException; }
在AuthenticationManager
接口的authenticate()
方法中可以有3種處理情況:
如果認(rèn)證成功,則返回一個(gè)Authentication
對(duì)象(通常將其authenticated屬性設(shè)置為true)。
如果認(rèn)證失敗,則拋出AuthenticationException
異常。
如果無(wú)法判斷成功或失敗,則返回null
。
AuthenticationException
是運(yùn)行時(shí)異常。 它通常由應(yīng)用程序以通用方式處理,具體取決于應(yīng)用程序的風(fēng)格或目的。 換句話說(shuō),通常不希望用戶代碼捕獲并處理它。 例如,一個(gè)Web UI將呈現(xiàn)一個(gè)頁(yè)面,該頁(yè)面說(shuō)明身份驗(yàn)證失敗,而后端HTTP服務(wù)將發(fā)送401響應(yīng),是否攜帶WWW-Authenticate
標(biāo)頭則取決于上下文。
AuthenticationManager
最常用的實(shí)現(xiàn)是ProviderManager
,它委派了AuthenticationProvider
實(shí)例鏈。 AuthenticationProvider
有點(diǎn)像AuthenticationManager
,但是它還有一個(gè)額外的方法,允許調(diào)用者查詢(xún)是否支持給定的Authentication
類(lèi)型:
public interface AuthenticationProvider { Authentication authenticate(Authentication authentication) throws AuthenticationException; boolean supports(Class<?> authentication); }
supports()
方法中的Class<?>
參數(shù)實(shí)際上是Class<? extends Authentication>
(僅會(huì)詢(xún)問(wèn)它是否支持將傳遞到authenticate()
方法中的內(nèi)容)。 通過(guò)委派給AuthenticationProviders
鏈,ProviderManager可以在同一應(yīng)用程序中支持多種不同的身份驗(yàn)證機(jī)制。 如果ProviderManager
無(wú)法識(shí)別特定的身份驗(yàn)證實(shí)例類(lèi)型,則將跳過(guò)該類(lèi)型。
ProviderManager
具有可選的父級(jí),如果所有提供程序都返回null
,則可以咨詢(xún)?cè)摳讣?jí)。 如果父級(jí)不可用,則空的Authentication
將導(dǎo)致AuthenticationException
。
有時(shí),應(yīng)用程序具有邏輯組的受保護(hù)資源(例如,與路徑模式/api/**
匹配的所有Web資源),并且每個(gè)組可以具有自己的專(zhuān)用AuthenticationManager
。 通常,每一個(gè)都是ProviderManager,它們共享一個(gè)父級(jí)。 因此,父級(jí)是一種“全局”資源,充當(dāng)所有providers的后備。
圖1. 使用ProviderManager
的AuthenticationManager
層次結(jié)構(gòu)
Spring Security提供了一些配置助手,可以快速獲取在應(yīng)用程序中設(shè)置的通用Authentication Managers功能。 最常用的幫助程序是AuthenticationManagerBuilder
,它非常適合設(shè)置內(nèi)存中、JDBC或LDAP用戶詳細(xì)信息,或添加自定義UserDetailsService
。 這是配置全局(父)AuthenticationManager的應(yīng)用程序的示例:
@Configuration public class ApplicationSecurity extends WebSecurityConfigurerAdapter { ... // web stuff here @Autowired public void initialize(AuthenticationManagerBuilder builder, DataSource dataSource) { builder.jdbcAuthentication().dataSource(dataSource).withUser("dave") .password("secret").roles("USER"); } }
此示例與Web應(yīng)用程序有關(guān),但是AuthenticationManagerBuilder
的用法更為廣泛(有關(guān)如何實(shí)現(xiàn)Web應(yīng)用程序安全性的詳細(xì)信息,請(qǐng)參見(jiàn)下文)。 注意,AuthenticationManagerBuilder
是@Autowired
到@Bean
中的方法中的-這就是使它構(gòu)建全局(父)AuthenticationManager的原因。 相反,如果我們這樣做的話:
@Configuration public class ApplicationSecurity extends WebSecurityConfigurerAdapter { @Autowired DataSource dataSource; ... // web stuff here @Override public void configure(AuthenticationManagerBuilder builder) { builder.jdbcAuthentication().dataSource(dataSource).withUser("dave") .password("secret").roles("USER"); } }
(在配置程序中使用方法的@Override
),那么AuthenticationManagerBuilder
僅用于構(gòu)建“本地” AuthenticationManager
,它是全局管理器的子級(jí)。 在Spring Boot應(yīng)用程序中,你可以使用@Autowired
將全局的管理器注入到另一個(gè)bean,但是除非你自己顯式公開(kāi)“本地”管理器,否則不能對(duì)本地管理器執(zhí)行此操作。
Spring Boot提供了一個(gè)默認(rèn)的全局AuthenticationManager
(只有一個(gè)用戶),除非你通過(guò)提供自己的AuthenticationManager
類(lèi)型的bean來(lái)?yè)屨妓?除非你主動(dòng)需要自定義全局AuthenticationManager
,否則默認(rèn)值本身就足夠安全,你不必?fù)?dān)心太多。 如果執(zhí)行任何構(gòu)建AuthenticationManager
的配置,則通??梢栽凇氨镜亍睂?duì)要保護(hù)的資源進(jìn)行配置,而不要去關(guān)心全局的默認(rèn)值。
身份認(rèn)證成功以后,我們接下來(lái)討論授權(quán),這里的核心策略是AccessDecisionManager
。 該框架提供了三種實(shí)現(xiàn),所有這三種實(shí)現(xiàn)都委托給AccessDecisionVoter
鏈,有點(diǎn)像ProviderManager
委托給AuthenticationProviders
。
AccessDecisionVoter
會(huì)考慮Authentication
(表示一個(gè)主體)和被ConfigAttributes
修飾的安全Object
:
boolean supports(ConfigAttribute attribute); boolean supports(Class<?> clazz); int vote(Authentication authentication, S object, Collection<ConfigAttribute> attributes);
Object
在AccessDecisionManager
和AccessDecisionVoter
的簽名中是完全通用的-它表示用戶可能要訪問(wèn)的任何內(nèi)容(Web資源或Java類(lèi)中的方法是兩種最常見(jiàn)的情況)。 ConfigAttributes
也相當(dāng)通用,用一些元數(shù)據(jù)來(lái)表示安全Object
的修飾,這些元數(shù)據(jù)確定訪問(wèn)它所需的權(quán)限級(jí)別。 ConfigAttribute
是一個(gè)接口,但是它只有一個(gè)非常通用的方法并返回String
,因此這些字符串以某種方式編碼資源所有者的意圖,表達(dá)有關(guān)允許誰(shuí)訪問(wèn)它的規(guī)則。 典型的ConfigAttribute
是用戶角色的名稱(chēng)(如ROLE_ADMIN
或ROLE_AUDIT
),并且它們通常具有特殊的格式(如ROLE_
前綴)或表示需要求值的表達(dá)式。
大多數(shù)人只使用默認(rèn)的AccessDecisionManager
,它是AffirmativeBased
的,即任何選民(voter)返回允許,則將授予訪問(wèn)權(quán)限。 任何定制都傾向于在選民中發(fā)生,要么增加新選民,要么修改現(xiàn)有選民的工作方式。
使用SpEL(Spring表達(dá)式語(yǔ)言)表達(dá)式的ConfigAttribute非常常見(jiàn),例如isFullyAuthenticated()&& hasRole('FOO')
。 AccessDecisionVoter
支持此功能,可以處理表達(dá)式并為其創(chuàng)建上下文。 為了擴(kuò)展可以處理的表達(dá)式的范圍,需要SecurityExpressionRoot
的自定義實(shí)現(xiàn),有時(shí)還需要實(shí)現(xiàn)SecurityExpressionHandler
。
Web層(用于UI和HTTP后端)中的Spring Security基于Servlet過(guò)濾器,因此通常首先了解過(guò)濾器的作用會(huì)很有幫助。 下圖顯示了單個(gè)HTTP請(qǐng)求的處理程序的典型分層。
客戶端向應(yīng)用程序發(fā)送請(qǐng)求,然后容器根據(jù)請(qǐng)求URI的路徑確定對(duì)它應(yīng)用哪些過(guò)濾器和哪個(gè)servlet。一個(gè)servlet最多只能處理一個(gè)請(qǐng)求,但是過(guò)濾器形成一個(gè)鏈,因此它們是有序的,實(shí)際上,如果某個(gè)過(guò)濾器要自己處理該請(qǐng)求,則其可以否決鏈的其余部分。過(guò)濾器還可以修改下游過(guò)濾器和Servlet中使用的請(qǐng)求和/或響應(yīng)。過(guò)濾器鏈的順序非常重要,Spring Boot通過(guò)兩種機(jī)制對(duì)其進(jìn)行管理:一種是Filter
類(lèi)型的@Bean
可以具有@Order
或?qū)崿F(xiàn)Ordered
,另一種是它們可以成為FilterRegistrationBean
本身的一部分,該Bean本身就維持了順序。一些現(xiàn)成的過(guò)濾器定義了自己的常量,以幫助表明它們相對(duì)彼此的順序(例如,Spring Session中的SessionRepositoryFilter
擁有的DEFAULT_ORDER
值為Integer.MIN_VALUE + 50
,這告訴我們此過(guò)濾器需要在過(guò)濾器鏈中比較靠前,但也并不阻止其他過(guò)濾器更靠前一些)。
Spring Security是作為鏈中的單個(gè)Filter
安裝的,其隱秘類(lèi)型為FilterChainProxy
,原因很快就會(huì)變得顯而易見(jiàn)。 在Spring Boot應(yīng)用程序中,安全過(guò)濾器是ApplicationContext
中的@Bean
,默認(rèn)情況下會(huì)安裝它,以便將其應(yīng)用于每個(gè)請(qǐng)求。 它安裝在SecurityProperties.DEFAULT_FILTER_ORDER
定義的位置,該位置又由FilterRegistrationBean.REQUEST_WRAPPER_FILTER_MAX_ORDER
錨定(Spring Boot應(yīng)用程序希望過(guò)濾器包裝請(qǐng)求并修改其行為時(shí)期望的最大順序)。 但是,還有更多要說(shuō)的:從容器的角度來(lái)看,Spring Security是一個(gè)過(guò)濾器,但是在內(nèi)部有其他過(guò)濾器,每個(gè)過(guò)濾器都扮演著特殊的角色。 這是一張圖:
圖2. Spring Security是單一Filter
,但將處理邏輯委托給一系列內(nèi)部過(guò)濾器
實(shí)際上,安全過(guò)濾器中甚至還有一層間接層:它通常作為DelegatingFilterProxy
安裝在容器中,而不必是Spring @Bean
。代理委托給一個(gè)始終為@Bean
的FilterChainProxy
,通常使用固定名稱(chēng)springSecurityFilterChain
。它是FilterChainProxy
,它包含所有內(nèi)部安全邏輯,這些安全邏輯在內(nèi)部排列為一個(gè)或多個(gè)過(guò)濾器鏈。所有過(guò)濾器都具有相同的API(它們都實(shí)現(xiàn)了Servlet規(guī)范中的Filter
接口),并且它們都有機(jī)會(huì)否決該鏈的其余部分。
在同一頂級(jí)FilterChainProxy
中可以有多個(gè)由Spring Security管理的過(guò)濾器鏈,而對(duì)于容器來(lái)說(shuō)都是未知的。 Spring Security過(guò)濾器包含一個(gè)過(guò)濾器鏈列表,并向與其匹配的第一個(gè)鏈調(diào)度(dispatch)一個(gè)請(qǐng)求。下圖顯示了基于匹配請(qǐng)求路徑(/foo/**
在/**
之前匹配)進(jìn)行的調(diào)度。這是很常見(jiàn)的,但不是匹配請(qǐng)求的唯一方法。此調(diào)度過(guò)程的最重要特征是,只有一個(gè)鏈可以處理請(qǐng)求。
圖3. Spring SecurityFilterChainProxy
將請(qǐng)求調(diào)度到匹配的第一個(gè)鏈
一個(gè)Spring Boot應(yīng)用程序,如果沒(méi)有自定義安全配置,會(huì)擁有多個(gè)(稱(chēng)為n)過(guò)濾器鏈,通常n = 6。 前(n-1)個(gè)鏈僅用于忽略靜態(tài)資源,例如/css/**
和/images/**
,以及錯(cuò)誤視圖/error
(路徑可以由SecurityProperties
配置bean中的security.ignored
控制)。 最后一個(gè)鏈與所有路徑/**
匹配,并且更活躍,包含用于身份認(rèn)證、授權(quán)、異常處理、會(huì)話處理、標(biāo)頭寫(xiě)入等邏輯。默認(rèn)情況下,該鏈中共有11個(gè)過(guò)濾器,但通常情況下用戶不必關(guān)心使用了哪個(gè)過(guò)濾器以及何時(shí)使用。
注意:容器不知道Spring Security內(nèi)部的所有過(guò)濾器這一事實(shí)很重要,尤其是在Spring Boot應(yīng)用程序中,默認(rèn)情況下,所有
Filter
類(lèi)型的@Beans
都會(huì)自動(dòng)向容器注冊(cè)。 因此,如果要向安全鏈中添加自定義過(guò)濾器,請(qǐng)不要使其成為@Bean
,或者干脆將其包裝在FilterRegistrationBean
中,在該Bean中顯式禁用了容器注冊(cè)的。
Spring Boot應(yīng)用程序中的默認(rèn)后備過(guò)濾器鏈(匹配/**
請(qǐng)求的那個(gè)鏈)具有SecurityProperties.BASIC_AUTH_ORDER
的預(yù)定義順序。 你可以通過(guò)設(shè)置security.basic.enabled = false
完全關(guān)閉它,也可以將其用作后備方式,而只是以較低的順序定義其他規(guī)則。 為此,只需添加類(lèi)型為WebSecurityConfigurerAdapter
(或WebSecurityConfigurer
)的@Bean
并使用@Order
注解。 例如:
@Configuration @Order(SecurityProperties.BASIC_AUTH_ORDER - 10) public class ApplicationConfigurerAdapter extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { http.antMatcher("/foo/**") ...; } }
這個(gè)bean將使Spring Security添加一個(gè)新的過(guò)濾器鏈并將其放置在后背過(guò)濾器鏈之前。
許多應(yīng)用程序?qū)σ唤M資源的訪問(wèn)規(guī)則可能完全不同于另外一組。 例如,對(duì)于一個(gè)承載了UI并且也支持API的應(yīng)用程序,可能其UI部分需要支持基于cookie(cookid-based)的身份認(rèn)證以及對(duì)登錄頁(yè)面的重定向,而其API部分則需要支持基于令牌(token-based)的身份認(rèn)證以及對(duì)未經(jīng)身份認(rèn)證的請(qǐng)求的401響應(yīng)。 每組資源都有其自己的WebSecurityConfigurerAdapter
以及唯一的順序和自己的請(qǐng)求匹配器。 如果匹配規(guī)則重疊,則最早的有序過(guò)濾器鏈將獲勝。
安全過(guò)濾器鏈(或等效的WebSecurityConfigurerAdapter
)具有請(qǐng)求匹配器,該請(qǐng)求匹配器用于確定是否將其應(yīng)用于HTTP請(qǐng)求。 一旦決定應(yīng)用特定的過(guò)濾器鏈,就不再應(yīng)用其他過(guò)濾器鏈。 但是在過(guò)濾器鏈中,可以通過(guò)在HttpSecurit
y配置器中設(shè)置其他匹配器來(lái)對(duì)授權(quán)進(jìn)行更精細(xì)的控制。 例如:
@Configuration @Order(SecurityProperties.BASIC_AUTH_ORDER - 10) public class ApplicationConfigurerAdapter extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { http.antMatcher("/foo/**") .authorizeRequests() .antMatchers("/foo/bar").hasRole("BAR") .antMatchers("/foo/spam").hasRole("SPAM") .anyRequest().isAuthenticated(); } }
配置Spring Security時(shí)最容易犯的一個(gè)錯(cuò)誤是忘記這些匹配器適用于不同的流程,一個(gè)是整個(gè)過(guò)濾器鏈的請(qǐng)求匹配器,另一個(gè)是僅選擇要應(yīng)用的訪問(wèn)規(guī)則。
如果你使用了Spring Boot執(zhí)行器(Actuator),則可能希望它的端點(diǎn)(endpoint)是安全的,默認(rèn)情況下確實(shí)將是安全的。 實(shí)際上,將執(zhí)行器添加到安全應(yīng)用程序后,你會(huì)獲得一條僅適用于執(zhí)行器端點(diǎn)的附加過(guò)濾器鏈。 它由僅匹配執(zhí)行器端點(diǎn)的請(qǐng)求匹配器來(lái)定義,并且其順序?yàn)?code>ManagementServerProperties.BASIC_AUTH_ORDER,該順序比默認(rèn)的SecurityProperties
后備過(guò)濾器的順序小5,因此會(huì)在后備過(guò)濾器處理之前請(qǐng)執(zhí)行。
如果你希望將應(yīng)用程序安全規(guī)則應(yīng)用于執(zhí)行器端點(diǎn),則可以添加一個(gè)比執(zhí)行器過(guò)濾器鏈順序更早的過(guò)濾器鏈,并且使之帶有包括所有執(zhí)行器端點(diǎn)的請(qǐng)求匹配器。 如果你更傾向于使用執(zhí)行器端點(diǎn)的默認(rèn)安全設(shè)置,那么最簡(jiǎn)單的方法是在執(zhí)行器端點(diǎn)之后但在后備過(guò)濾器鏈之前(例如ManagementServerProperties.BASIC_AUTH_ORDER +1
)添加自己的過(guò)濾器。 例如:
@Configuration @Order(ManagementServerProperties.BASIC_AUTH_ORDER + 1) public class ApplicationConfigurerAdapter extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { http.antMatcher("/foo/**") ...; } }
注意:Web層中的Spring Security當(dāng)前與Servlet API綁定,因此僅當(dāng)在Servlet容器中運(yùn)行應(yīng)用程序時(shí)才真正適用,不管是嵌入式的容器還是獨(dú)立式的容器。 但是,它不依賴(lài)于Spring MVC或Spring Web棧的其它部分,因此可以在任何servlet應(yīng)用程序中使用,例如使用JAX-RS的servlet應(yīng)用程序。
除了支持Web應(yīng)用程序安全外,Spring Security還支持將訪問(wèn)規(guī)則應(yīng)用于Java方法執(zhí)行。 對(duì)于Spring Security,這只是另一種類(lèi)型的“受保護(hù)資源”。 對(duì)于用戶來(lái)說(shuō),這意味著使用相同的ConfigAttribute
字符串格式(例如角色或表達(dá)式)來(lái)聲明訪問(wèn)規(guī)則,但在代碼中的不同位置。 第一步是啟用方法安全性,例如在應(yīng)用程序的頂級(jí)配置中:
@SpringBootApplication @EnableGlobalMethodSecurity(securedEnabled = true) public class SampleSecureApplication { }
然后我們就可以直接修飾方法資源,例如:
@Service public class MyService { @Secured("ROLE_USER") public String secure() { return "Hello Security"; } }
此示例是一種使用安全方法的服務(wù)。 如果Spring創(chuàng)建了這種類(lèi)型的@Bean
,則它將被代理,并且在實(shí)際執(zhí)行該方法之前,調(diào)用者必須經(jīng)過(guò)安全攔截器。 如果訪問(wèn)被拒絕,則調(diào)用者將得到AccessDeniedException
異常,而不是實(shí)際的方法結(jié)果。
方法上還可以使用其他注解來(lái)強(qiáng)制執(zhí)行安全性約束,特別是@PreAuthorize
和@PostAuthorize
,它們可以使你編寫(xiě)分別包含對(duì)方法參數(shù)和返回值的引用的表達(dá)式。
小貼士:結(jié)合使用Web安全性和方法安全性并不少見(jiàn)。 過(guò)濾器鏈提供了用戶體驗(yàn)功能,例如身份認(rèn)證和重定向到登錄頁(yè)面等,而方法安全性在更精細(xì)的級(jí)別上提供了保護(hù)。
Spring Security從根本上講是線程綁定的,因?yàn)樗枰巩?dāng)前經(jīng)過(guò)身份驗(yàn)證的主體可供各種下游使用者使用。 基本構(gòu)件是SecurityContext
,它可以包含一個(gè)Authentication
(當(dāng)用戶登錄成功以后,它將被顯式注明為authenticated
)。 你始終可以通過(guò)SecurityContextHolder
中的靜態(tài)方法訪問(wèn)和操作SecurityContext
,而該方法里面其實(shí)是簡(jiǎn)單地操作TheadLocal,例如
SecurityContext context = SecurityContextHolder.getContext(); Authentication authentication = context.getAuthentication(); assert(authentication.isAuthenticated);
用戶應(yīng)用程序代碼執(zhí)行此操作并不常見(jiàn),但是如果在你需要編寫(xiě)自定義身份認(rèn)證過(guò)濾器時(shí)可能會(huì)很有用(盡管即使如此,Spring Security中也可以使用基類(lèi)來(lái)避免使用SecurityContextHolder
)。
如果需要訪問(wèn)Web端點(diǎn)中當(dāng)前已認(rèn)證的用戶,則可以在@RequestMapping
中使用方法參數(shù)。 例如。
@RequestMapping("/foo") public String foo(@AuthenticationPrincipal User user) { ... // do stuff with user }
該注解將當(dāng)前的Authentication
從SecurityContext
中取出,并調(diào)用其getPrincipal()
方法以產(chǎn)生方法參數(shù)。 Authentication
中的主體(Principal)的類(lèi)型取決于用于身份認(rèn)證的AuthenticationManager
,因此這也是一個(gè)獲得對(duì)用戶數(shù)據(jù)的類(lèi)型安全引用的有用的小技巧。
如果使用Spring Security,則HttpServletRequest
中的Principal
的類(lèi)型將為Authentication
,因此你也可以直接使用它:
@RequestMapping("/foo") public String foo(Principal principal) { Authentication authentication = (Authentication) principal; User = (User) authentication.getPrincipal(); ... // do stuff with user }
如果你需要編寫(xiě)在不使用Spring Security的情況下仍可以正常工作的代碼,那么這就會(huì)很有用(你需要在加載Authentication
類(lèi)時(shí)更具防御性)。
由于SecurityContext
是線程綁定的,因此,如果要執(zhí)行任何調(diào)用安全方法的后臺(tái)處理,例如使用@Async,你需要確保傳播該SecurityContext
。 簡(jiǎn)單歸結(jié)起來(lái)就是,要將SecurityContext
與在后臺(tái)執(zhí)行的任務(wù)(Runnable
,Callable
等)包裝在一起。 Spring Security提供了一些幫助程序,例如Runnable
和Callable
的包裝器,可以使上述操作變得簡(jiǎn)單。 要將SecurityContext
傳播到@Async
方法,你需要提供AsyncConfigurer
并確保Executor
具有正確的類(lèi)型:
@Configuration public class ApplicationConfiguration extends AsyncConfigurerSupport { @Override public Executor getAsyncExecutor() { return new DelegatingSecurityContextExecutorService(Executors.newFixedThreadPool(5)); } }
“如何理解Spring Security架構(gòu)”的內(nèi)容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業(yè)相關(guān)的知識(shí)可以關(guān)注億速云網(wǎng)站,小編將為大家輸出更多高質(zhì)量的實(shí)用文章!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。