1. Spring Security自定義攔截器
HttpSecurity實際上就是在配置Spring security的過濾器鏈,比如:CSRF,CORS,表單登錄等,每個配置器對應一個過濾器,可以通過HttpSecurity配置過濾器的行為。
甚至可以像CRSF一樣直接關閉過濾器,例如:SessionManagement
Spring Security通過SessionManagermentConfigurer來配置SessionManagerment的行為,與SessionManagermentConfigurer類似的配置器還有CorsConfigurer,RememberMeConfigurer等,他們都實現了SecurityConfigurer的標准介面。
SessionManagementConfigurer是在configure方法中將最終的SessionManagementFilter插入過濾器鏈來實現會話管理的。
除了Spring security提供的過濾器外,我們還可以添加自己的過濾器以實現更多的功能,這些都是可以在HttpSecurity中實現
雖然Spring Security 的過濾器鏈對過濾器沒有特殊要求,只要繼承了Filter即可,但是在Spring體系中,推薦使用OnePerRequestFilter來實現,它可以確保一次請求只會通過一次該過濾器(Filter實際並不能保證這一點)
其實關於這個自定義Filter,我個人感覺有個比較danteng的地方,比如:我們在實現圖片驗證碼或者一些其他的登錄相關的驗證碼的時候,我們可能會做到在賬號跟密碼驗證了之後對這個驗證碼進行驗證,然後我就必須有個這種操作: http.addFilterBefore(filter,.class); 因為如果驗證碼驗證錯誤,我們就不需要也沒必要再往後驗證了,所以我們得知道我們定義的這個驗證碼過濾器得在什麼時候驗證在哪個過濾器之前或者之後驗證,那麼問題來了,或許我們並不知道Spring Security給我們提供了哪些或者什麼樣的過濾器,我們得去記住這些過濾器,這就有點不友好了。在HttpSecurityBuilder介面中,有一段這樣的注釋:
非常爽眼~
2. Spring Security源碼(一):認證、授權、過濾器鏈
因為看了很多博客,發現很多人的使用風格都不一樣,有點懵。感覺最好的方法就是多看一些源碼,然後自己選擇想要的使用方式。
spring security版本:2.1.6.RELEASE
這里先講這三種的關系
AuthenticationManager、ProviderManager、AuthenticationProvider
封裝了用戶身份信息
一個介面,只有一個方法
ProviderManager是AuthenticationManager的實現類,提供了基本認證實現邏輯和流程;
先看這個方法這個方法,是 用來認證 的方法
關鍵點
AuthenticationProvider 本身也就是一個 介面 ,它有實現類 和的 子類DaoAuthenticationProvider
只有 兩個 方法
總結
這是一個抽象類,是 模板模 式。定義好了認證流程,我們去實現流程中的一些 環節 方法。達到了 自定義認證 的效果
的子類,實現了一些 抽象方法
retrieveUser
主要就是用 UserDetailsService 去查找用戶
createSuccessAuthentication
本質還是調用了父類的方法,就是新建了一個Authentication,然後將 UserDetails 的 信息 傳遞過去
UserDetailsService是一個介面,提供了一個方法
感覺這個介面沒什麼用,就是用來管理用戶類的
SS在http後台中起作用主要是基於 Servlet Filters 的,我們先來看看什麼是 Filter 是如何作用在 Servlet 中的。
springSecurityFilterChain 是個介面 , DefaultSecurityFilterChain 是它的實現類,而DefaultSecurityFilterChain 內部存在這一個 Filters 列表 ,關於SS中的過濾器和他們的執行順序(Order)可以查看 官方文檔 ,當我們需要自定義Filter的時候就會用到。 當請求到來時,在 ss 里邊的 Filter就會作用請求,如下圖 :
在上面我們說到了SS有 自己的一條過濾器鏈 ,下面就是截圖:(執行順序就是集合中的順序)
下面說一下幾個 比較重要的 Filter 的 處理邏輯
整個調用流程是,先調用其父類 .doFilter() 方法,然後再執行 .attemptAuthentication() 方法進行驗證;
父類是 (又是模板模式,子類實現抽象方法,父類定好流程)
requiresAuthentication
判斷是否需要當前filter處理,就是判斷路徑、請求方法等等
以的構造方法為例
successfulAuthentication
這里的認證就是 第一節的內容 ( this.getAuthenticationManager().authenticate(authRequest) )
從上圖中過濾器的執行順序圖中可以看出 AnonymousAuthenticationFilter 過濾器是在 等過濾器之後 ,如果它前面的過濾器 都沒有認證成功 ,Spring Security則為當前的SecurityContextHolder中添加一個Authenticaiton 的匿名實現類 AnonymousAuthenticationToken;
總結
ExceptionTranslationFilter 異常處理過濾器,該過濾器用來處理在系統 證授權過程 中拋出的異常(也就是下一個過濾器FilterSecurityInterceptor),主要是 處理 AuthenticationException 和 AccessDeniedException 。
此過濾器為認證授權過濾器鏈中 最後一個過濾器 ,該過濾器之後就是請求真正的 /xx服務
Spring Security默認使用 AffirmativeBased 實現 AccessDecisionManager 的 decide 方法來實現授權
到此位置 authentication 當前用戶信息,fl當前訪問的 資源路徑及attributes當前資源路徑的決策 (即是否需要認證)。剩下就是 判斷 當前用戶的角色Authentication.authorites 是否許可權 訪問決策訪問當前資源fi
Spring Security 核心過濾器鏈分析
3. SpringCloud Gateway-添加cookies的過濾器
@Component
public class CookiesFilter implements Ordered, GlobalFilter {
@Override
public Mono filter(ServerWebExchange exchange, GatewayFilterChain chain) {
ServerHttpRequest request = exchange.getRequest().mutate().headers((httpHeaders) -> {
String csrf =new HttpCookie("csrf", "3838a26d-07f7-11e9-b5f7").toString();
String ssn =new HttpCookie("ssn", "MTU0NT").toString();
httpHeaders.set("Cookie", csrf+";"+ssn);
}).build();
return chain.filter(exchange.mutate().request(request).build());
}
@Override
public int getOrder() {
return -100;
}
}
4. SpringBoot系列:4.session和鑒權—過濾器和攔截器
本文主要介紹下,SpringBoot的web項目中,
使用redis保存並共享session,可以實現集群內的登錄信息共享。SpringBoot項目中,通過在 application.yml 增加redis的配置,即可實現對session的存儲和修改。
那麼session是在何時被處理的?session的key又是如何生成的呢?這里實際使用了web項目中的過濾器。
在SpringBoot的web項目中,啟動的tomcat在處理http請求時,有一個很重要的類: ApplicationFilterChain 。每個http請求在處理時都會通過這個類。這個類負責按順序處理全部已注冊的 Filter ,也就是過濾器。通過實現tomcat中的 Filter 介面,就可以定義一個過濾器。
在SpringBoot中的web項目中,有幾個默認的過濾器,其中一個就是用來處理session的: SessionRepositoryFilter
SessionRepositoryFilter 主要的成員是兩個介面,都有多個可選的實現類,通過這兩個成員就實現了對session的解析。
當然也可以實現一個自己的過濾器,主要有兩種方式:
下面我們使用第一種方式實現一個限制指定IP的過濾器:
通過過濾器解析session後,就可以根據session中保存的內容,判斷當前登錄的用戶許可權。
這里是通過一個攔截器實現的,在攔截器中可以直接通過 HttpServletRequest.getSession() 方法直接獲取session的信息。
一個簡單的攔截器實現如下:
定義之後要注冊到處理流程中:
先來看下過濾器和攔截器的執行順序,通過debug得到的執行順序如下圖:
在大部分場景中,過濾器和攔截器都是可互換的,使用哪個都可以。
過濾器和攔截器也有些區別,這里不談實現和規范的差異,就說下使用中可能涉及的區別:
最後對於過濾器和攔截器的應用場景,說下個人的總結。基於執行順序,方法參數和SpringBoot中的一些實現類來看。
以上內容屬個人學習總結,如有不當之處,歡迎在評論中指正