亚洲激情专区-91九色丨porny丨老师-久久久久久久女国产乱让韩-国产精品午夜小视频观看

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

SecurityFilterChain的構建過程是怎樣的

發布時間:2021-10-26 10:48:32 來源:億速云 閱讀:171 作者:iii 欄目:編程語言

本篇內容介紹了“SecurityFilterChain的構建過程是怎樣的”的有關知識,在實際案例的操作過程中,不少人都會遇到這樣的困境,接下來就讓小編帶領大家學習一下如何處理這些情況吧!希望大家仔細閱讀,能夠學有所成!

Spring Security嵌入Servlet的核心Bean為一個名稱為 springSecurityFilterChain 的過濾器。該過濾器是Spring Security的核心入口。

無論何種方式的Web應用,Spring Security都是從IOC中獲取“springSecurityFilterChain”的,這個Bean的注冊入口只有一個,在類WebSecurityConfiguration中,該配置對象由注解@EnableWebSecurity開啟

@Bean(name = AbstractSecurityWebApplicationInitializer.DEFAULT_FILTER_NAME)
public Filter springSecurityFilterChain() throws Exception {
...
return webSecurity.build();
}

建造者模式:WebSecurity,建造的產品為:Filter,具體類型為FilterChainProxy

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

模板方法模式:AbstractConfiguredSecurityBuilder,模板方法為建造者的build方法,模板化之后調用doBuild方法,doBuild仍然是一個模板方法

@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;
}
}

核心構建方法 performBuild 方法在子類中具體實現,此處構建類為WebSecurity

@Override
protected Filter performBuild() throws Exception {
 // 鏈長度
 int chainSize = ignoredRequests.size() + securityFilterChainBuilders.size();
 // SecurityFilterChain的構建
 List<SecurityFilterChain> securityFilterChains = new ArrayList<>(chainSize);
 // 第一部分:來自不需要安全保護請求:ignoredRequest
 for (RequestMatcher ignoredRequest : ignoredRequests) {
   securityFilterChains.add(new DefaultSecurityFilterChain(ignoredRequest));
 }
 // 第二部分:來自需要安全保護請求:securityFilterChainBuilders
 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;
}

第一篇文章也說了,FilterChainProxy代理的多條SecurityFilterChain最終只能走一條,因此SecurityFilterChain來源十分重要,上面的代碼說明來源是2部分,這兩部分都是WebSecurity的私有屬性,也就是可以在任何可以獲得WebSecurity實例的位置進行配置,但是一般都會按照規約進行,防止代理混亂、不易讀。以下WebSecurity的2個屬性分別表示2種來源

private final List<RequestMatcher> ignoredRequests = new ArrayList<>();

private final List<SecurityBuilder<? extends SecurityFilterChain>> securityFilterChainBuilders = new ArrayList<>();

這兩種來源的SecurityFilterChain其實涉及了2種構建者:WebSecurity和HttpSecurity,前者基于Web應用(一般就是MVC)來構建安全,后者基于請求-響應(一般而言就是HTTP)來構建安全。

WebSecurity

基于Servlet的Web應用的安全訪問控制,Spring Security與Spring MVC緊密集成。在WebSecurity可以進行整體的配置,優先級最高

來源之一:ignoredRequests

WebSecurity內部類IgnoredRequestConfigurer提供了配置ignoredRequests的功能,并且提供了mvcMatchers(String... mvcPatterns)和mvcMatchers(HttpMethod method,String... mvcPatterns)兩種配置入口。通過WebSecurity#ignoring方法就能拿到該對象實例并完成配置:該配置符合鏈式調用,每個IgnoredRequestConfigurer都可以構建一條SecurityFilterChain

@Override
public void configure(WebSecurity web) throws Exception {
  super.configure(web);
  // 獲取IgnoredRequest配置對象
  web.ignoring()
      // 鏈式調用   
     .mvcMatchers("/login")
      // 鏈式調用  
     .mvcMatchers("/home")
  ;
}

HttpSecurity

基于網絡請求的安全訪問控制,在Servlet中網絡請求主要在Filter中,這部分主要是配置的Http請求流轉過程中的安全。

來源之一:securityFilterChainBuilders

大部分開發使用的就是這種來源,每個實例構建一條SecurityFilterChain。WebSecurity提供了addSecurityFilterChainBuilder方法來配置,因此通過WebSecurity實例也能完成配置,但是securityFilterChainBuilder構建流程復雜,一般都使用Spring Security提供的內置方法來簡化這個流程,例如在WebSecurityConfigurerAdapter#init中就默認調用了addSecurityFilterChainBuilder(HttpSecurity)

@Override
protected void configure(HttpSecurity http) throws Exception {
 http
  .authorizeRequests()
  .antMatchers("/").permitAll()
  .anyRequest().authenticated()
  .and()
  .formLogin()
  .loginPage("/login")
  .permitAll()
  .and()
  .logout()
  .permitAll();
}
Spring Security 認證、授權核心入口:FilterSecurityInterceptor

針對方法級別的攔截:區分為前置攔截:beforeInvocation和后置攔截:afterInvocation,前后攔截原理基本一致。

這是開發者經常接觸方式,這種模式引入一個專有名詞:ConfigAttribute,直譯:屬性配置,但是對于開發而已可以稱為:安全訪問規則

可以對任何路徑配置(每個Controller方法其實對應的就是訪問路徑)安全訪問規則。權限標識屬于一種安全訪問規則。

對安全訪問規則ConfigAttribute能否滿足訪問資源的權限的決斷,由AccessDecisionManager處理,AccessDecisionManager特定訪問規則的web資源能否被訪問。

而AccessDecisionManager做出決斷需要當前賬號的認證信息,因此在做出決斷之前會嘗試通過AuthenticationManager獲取當前請求的身份認證信息。

這里獲取認證信息、做出訪問決斷是Spring Security的另一個核心,會單獨說明,本篇文章主要描述SecurityFilterChain的構建。

authorizeRequests --> ExpressionUrlAuthorizationConfigurer --> FilterSecurityInterceptor

功能:配置基于請求路徑的安全訪問規則:ConfigAttribute

HttpSecurity主要配置Filter鏈,也就是SecurityFilterChain的來源,也是最常見的,當然也是最重要的,下面為默認的配置

http = new HttpSecurity(objectPostProcessor, authenticationBuilder,sharedObjects);
if (!disableDefaults) {
	// @formatter:off
	http
		.csrf().and()
		.addFilter(new WebAsyncManagerIntegrationFilter())
		.exceptionHandling().and()
		.headers().and()
		.sessionManagement().and()
		.securityContext().and()
		.requestCache().and()
		.anonymous().and()
		.servletApi().and()
		.apply(new DefaultLoginPageConfigurer<>()).and()
		.logout();
	// @formatter:on
	ClassLoader classLoader = this.context.getClassLoader();
	// 拿出IOC容器中所有AbstractHttpConfigurer具體類,逐個配置
	List<AbstractHttpConfigurer> defaultHttpConfigurers = 
		SpringFactoriesLoader.loadFactories(AbstractHttpConfigurer.class, classLoader);
	for (AbstractHttpConfigurer configurer : defaultHttpConfigurers) {
		http.apply(configurer);
	}
}
// 常見的配置方法:protected void configure(HttpSecurity http) throws Exception {
configure(http);

這里默認會加入10個Configurer,每個對應一個Filter,defaultHttpConfigurers默認為空,可以自定義Bean來注冊,會覆蓋默認配置,再加上配置的WebAsyncManagerIntegrationFilter和平時常用的formLogin總共12個Filter,各種Filter之間時有序的。

configure(http);方法則是開發者重寫的方法,用于擴展SecurityFilterChain中的Filter,同樣此處定義會覆蓋前面默認配置,每種configurer都與對應一種Filter

ChannelSecurityConfigurer --> ChannelProcessingFilter

功能:配置Web請求通道轉換后重定向,默認兩種:安全的https->443、不安全的http->80,不區分的權限標識為:"ANY_CHANNEL"。如果不需要https保護接口,則不用配置該過濾器。

WebAsyncManagerIntegrationFilter

功能:將SecurityContext配置到異步請求WebAsyncManager中,MVC支持異步Controller,返回對象為:DeferredResult等

ConcurrentSessionFilter

功能:對于session存在的請求,驗證session是否過期,如果過期,則調用doLogout方法,否則更新session的訪問時間。默認不啟用該Filter,可以在sessionManagement#maximumSessions控制。

securityContext --> SecurityContextPersistenceFilter

功能:持久化SecurityContext,即Security上下文,使得能從線程中獲取到當前登錄用戶的信息,持久化方式默認是HttpSessionSecurityContextRepository即服務器Session,key="SPRING_SECURITY_CONTEXT"。

headers --> HeadersConfigurer --> HeaderWriterFilter

功能:在請求響應的頭部添加自定義信息

cors -> CorsConfigurer -> CorsFilter

功能:跨域處理,注意這個過濾器是Spring Security內部過濾器,在優先級更高過濾器中就返回的響應不會具有跨域能力

csrf --> CsrfConfigurer --> CsrfFilter

功能:跨站請求攻擊防御,默認對"GET", "HEAD", "TRACE", "OPTIONS"請求進行CSRF保護,默認為session中保存CsrfToken,前后端進行驗證

logout --> LogoutConfigurer --> LogoutFilter

功能:匹配路徑登出

formLogin --> FormLoginConfigurer --> UsernamePasswordAuthenticationFilter

功能:使用賬號、密碼模式的UsernamePasswordAuthenticationToken身份認證

DefaultLoginPageConfigurer --> DefaultLoginPageGeneratingFilter && DefaultLogoutPageGeneratingFilter

功能: 在未指定登錄登出頁面時,生成默認的頁面

httpBasic --> HttpBasicConfigurer --> BasicAuthenticationFilter

功能:通過UsernamePasswordAuthenticationToken處理請求頭中Basic格式的Authorization認證信息

requestCache --> RequestCacheConfigurer --> RequestCacheAwareFilter

功能:用來恢復登錄流程中被中斷(認證失敗)的請求。

在RequestCacheConfigurer中對HttpRequest緩存條件加了以下默認限制

  • Csrf開啟時:只能為GET請求

  • 不緩存網站圖標請求:即路徑不能匹配“/**/favicon.*”

  • 不緩存這三種媒體類型MediaType:"application/json"、"multipart/form-data"、"text/event-stream"

  • 不緩存xjax請求,即請求頭"X-Requested-With"不能為:"XMLHttpRequest"

servletApi --> ServletApiConfigurer --> SecurityContextHolderAwareRequestFilter

功能:實現Servlet3 API接口,主要在SecurityContextHolderAwareRequestWrapper重寫實現,例如getRemoteUser、getUserPrincipal、isUserInRole

rememberMe --> RememberMeConfigurer --> RememberMeAuthenticationFilter

功能:當用戶沒有登錄而訪問web資源時,可以從cookie或者內存中找出身份識別信息從而靜默登錄

anonymous --> AnonymousConfigurer --> AnonymousAuthenticationFilter

功能:當Security Context中認證信息為null時設置Security Context=AnonymousAuthenticationToken,默認權限為"ROLE_ANONYMOUS"

sessionManagement --> SessionManagementConfigurer --> SessionManagementFilter

功能:針對未持久化過SecurityContext的請求進行session會話固定(Session fixation)保護和限制用戶打開會話數量。

exceptionHandling --> ExceptionHandlingConfigurer --> ExceptionTranslationFilter

功能:處理Spring Security流程中出現的異常,主要就是AuthenticationException和AccessDeniedException異常,獲取到異常一般都會交給對應的AuthenticationEntryPoint#commence去處理,但是非AnonymousAuthenticationToken或者RememberMeAuthenticationToken產生的AccessDeniedException會交給過濾器中的accessDeniedHandler來處理(例如:403)

過濾器有排序的,整體排序如下

FilterComparator() {
	Step order = new Step(INITIAL_ORDER, ORDER_STEP);
	put(ChannelProcessingFilter.class, order.next());
	put(ConcurrentSessionFilter.class, order.next());
	put(WebAsyncManagerIntegrationFilter.class, order.next());
	put(SecurityContextPersistenceFilter.class, order.next());
	put(HeaderWriterFilter.class, order.next());
	put(CorsFilter.class, order.next());
	put(CsrfFilter.class, order.next());
	put(LogoutFilter.class, order.next());
	filterToOrder.put("org.springframework.security.oauth3.client.web.OAuth3AuthorizationRequestRedirectFilter",order.next());
	filterToOrder.put("org.springframework.security.saml2.provider.service.servlet.filter.Saml2WebSsoAuthenticationRequestFilter",order.next());
	put(X509AuthenticationFilter.class, order.next());
	put(AbstractPreAuthenticatedProcessingFilter.class, order.next());
	filterToOrder.put("org.springframework.security.cas.web.CasAuthenticationFilter",order.next());
	filterToOrder.put("org.springframework.security.oauth3.client.web.OAuth3LoginAuthenticationFilter",order.next());
	filterToOrder.put("org.springframework.security.saml2.provider.service.servlet.filter.Saml2WebSsoAuthenticationFilter",order.next());
	put(UsernamePasswordAuthenticationFilter.class, order.next());
	put(ConcurrentSessionFilter.class, order.next());
	filterToOrder.put("org.springframework.security.openid.OpenIDAuthenticationFilter", order.next());
	put(DefaultLoginPageGeneratingFilter.class, order.next());
	put(DefaultLogoutPageGeneratingFilter.class, order.next());
	put(ConcurrentSessionFilter.class, order.next());
	put(DigestAuthenticationFilter.class, order.next());
	filterToOrder.put("org.springframework.security.oauth3.server.resource.web.BearerTokenAuthenticationFilter", order.next());
	put(BasicAuthenticationFilter.class, order.next());
	put(RequestCacheAwareFilter.class, order.next());
	put(SecurityContextHolderAwareRequestFilter.class, order.next());
	put(JaasApiIntegrationFilter.class, order.next());
	put(RememberMeAuthenticationFilter.class, order.next());
	put(AnonymousAuthenticationFilter.class, order.next());
	filterToOrder.put("org.springframework.security.oauth3.client.web.OAuth3AuthorizationCodeGrantFilter",order.next());
	put(SessionManagementFilter.class, order.next());
	put(ExceptionTranslationFilter.class, order.next());
	put(FilterSecurityInterceptor.class, order.next());
	put(SwitchUserFilter.class, order.next());
}

注意排序中FilterSecurityInterceptor的優先級別很低,防御的是Web中方法級別的安全。最終SecurityFilterChain來源如圖示下

SecurityFilterChain的構建過程是怎樣的

“SecurityFilterChain的構建過程是怎樣的”的內容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業相關的知識可以關注億速云網站,小編將為大家輸出更多高質量的實用文章!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

吴桥县| 星座| 白城市| 盐亭县| 岑溪市| 桐柏县| 赤城县| 华容县| 红桥区| 桦南县| 湖北省| 恩平市| 鄯善县| 盐山县| 长乐市| 诸暨市| 綦江县| 三原县| 哈密市| 叙永县| 康乐县| 万盛区| 娄底市| 商河县| 靖宇县| 延庆县| 千阳县| 荆门市| 沈阳市| 灵台县| 黎川县| 固安县| 名山县| 阿拉善左旗| 逊克县| 广元市| 凉山| 邹平县| 丽江市| 额尔古纳市| 无极县|