Spring Security 在 Servlet 請求中實現(xiàn)鑒權(quán)
1. 前言
Servlet 是 Java Web 應(yīng)用的最常見場景,Spring Security 對 Servlet 的權(quán)限認定過程實現(xiàn)了規(guī)范化和流程化。
本節(jié)主要討論在 Servlet 應(yīng)用中,如何通過 Spring Security 實現(xiàn)鑒權(quán)。
2. Servlet 權(quán)限控制的流程
Servlet 鑒權(quán)主要圍繞著 FilterSecurityInterceptor
類展開,該類作為一個安全過濾器,被放置在 FilterChainProxy
中。
圖 1. Servlet 請求鑒權(quán)流程
具體流程如下:
FilterSecurityInterceptor
從SecurityContextHolder
中獲取Authentication
對象;FilterSecurityInterceptor
從HttpServletRequest
、HttpServletREsponse
、FilterChain
中創(chuàng)建FilterInvocation
對象;- 將創(chuàng)建的
FilterInvocation
對象傳遞給SecurityMetadataSource
用來獲取ConfigAttribute
對象集合; - 最后,將
Authentication
、FilterInvocation
和ConfigAttribute
對象傳遞給AccessDecisionManager
實例驗證權(quán)限:- 如果驗證失敗,將拋出
AccessDeniedException
異常,并由ExceptionTranslationFilter
接收并處理; - 如果驗證通過,
FilterSecurityInterceptor
將控制權(quán)交還給FilterChain
,使程序繼續(xù)執(zhí)行。
- 如果驗證失敗,將拋出
3. Servlet 權(quán)限控制的配置實現(xiàn)
默認情況下,Spring Security 的權(quán)限要求所有的請求都需要首先通過認證。相當(dāng)于以下配置描述:
protected void configure(HttpSecurity http) throws Exception {
http
// ...
.authorizeRequests(authorize -> authorize
.anyRequest().authenticated()
);
}
如果我們需要配置 Spring Security 對不同請求有不同的處理規(guī)則時,可通過以下方式修改配置:
protected void configure(HttpSecurity http) throws Exception {
http
// ...
.authorizeRequests(authorize -> authorize
.mvcMatchers("/resources/**", "/signup", "/about").permitAll()
.mvcMatchers("/admin/**").hasRole("ADMIN")
.mvcMatchers("/db/**").access("hasRole('ADMIN') and hasRole('DBA')")
.anyRequest().denyAll()
);
}
以上這段代碼實現(xiàn)了如下功能:
- 指定了多種規(guī)則,每種規(guī)則按照其配置的順序決定優(yōu)先級;
- 匹配了多個 URL 規(guī)則,對于
/resources
、/signup
、/about
允許任何用戶訪問; - 任何以
/admin/
開頭的地址都要求用戶具有管理員權(quán)限ROLE_ADMIN
,其中ROLE_
前綴是 Spring Security 默認添加的,用戶無需做特殊處理; - 任何以
/db/
為開頭的地址需要同時擁有ROLE_ADMIN
和ROLE_DBA
角色; - 沒有被上述 URL 地址匹配的地址都將被禁止訪問,加上這一條非常有助于提升系統(tǒng)的安全性。
4. 小結(jié)
本節(jié)討論了如何用 Spring Security 規(guī)范化 Servlet 鑒權(quán)過程:
- Spring Security 對 Servlet 請求的權(quán)限控制,主要依賴于
FilterSecurityInterceptor
實現(xiàn); - Spring Security 默認對每一個 Servlet 請求都要求用戶已通過認證;
- Spring Security 支持對 Servlet 的不同 URL 規(guī)則配置不同的權(quán)限規(guī)則。
下節(jié)我們討論如何通過「訪問控制表達式」實現(xiàn)多樣化的鑒權(quán)規(guī)則。