- 原理
Spring Security是一個功能強(qiáng)大且高度可定制的身份驗證和訪問控制框架贰您。它是用于保護(hù)基于Spring的應(yīng)用程序的實際標(biāo)準(zhǔn)。
Spring Security是一個框架赋咽,致力于為Java應(yīng)用程序提供身份驗證和授權(quán)。與所有Spring項目一樣窘疮,Spring Security的真正強(qiáng)大之處在于可以輕松擴(kuò)展以滿足自定義要求
Spring Security的體系結(jié)構(gòu)旨在將身份驗證與授權(quán)分開慌烧,并具有策略和擴(kuò)展點(diǎn)。
1.身份驗證
public interface AuthenticationManager {
Authentication authenticate(Authentication authentication)
throws AuthenticationException;
}
authenticate()方法中的三件事之一:
- 如果可以驗證輸入是否代表有效的委托人膏燕,則返回Authentication(通常為authenticated=true)钥屈。
- AuthenticationException如果它認(rèn)為輸入代表無效的主體,則拋出一個坝辫。
- null如果無法決定篷就,則返回。
//An AuthenticationProvider有點(diǎn)像an近忙,AuthenticationManager但是它有一個額外的方法竭业,允許調(diào)用者查詢是否支持給定Authentication類型:
public interface AuthenticationProvider {
Authentication authenticate(Authentication authentication)
throws AuthenticationException;
/**
*
*/
boolean supports(Class<?> authentication);
}
@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");
}
}
2.訪問控制
安全過濾器鏈 WebSecurityConfigurerAdapter
筆記:
5.1。認(rèn)證方式
5.1.1银锻。認(rèn)證支持
5.1.2永品。密碼儲存
- DelegatingPasswordEncoder
確保使用當(dāng)前密碼存儲建議對密碼進(jìn)行編碼
允許以現(xiàn)代和舊式格式驗證密碼
允許將來升級編碼
//.創(chuàng)建默認(rèn)的DelegatingPasswordEncoder
PasswordEncoder passwordEncoder =
PasswordEncoderFactories.createDelegatingPasswordEncoder();
//創(chuàng)建自定義DelegatingPasswordEncoder
String idForEncode = "bcrypt";
Map encoders = new HashMap<>();
encoders.put(idForEncode, new BCryptPasswordEncoder());
encoders.put("noop", NoOpPasswordEncoder.getInstance());
encoders.put("pbkdf2", new Pbkdf2PasswordEncoder());
encoders.put("scrypt", new SCryptPasswordEncoder());
encoders.put("sha256", new StandardPasswordEncoder());
PasswordEncoder passwordEncoder =
new DelegatingPasswordEncoder(idForEncode, encoders);
- BCryptPasswordEncoder
- Argon2PasswordEncoder
- Pbkdf2PasswordEncoder
Spring Security 默認(rèn)使用DelegatingPasswordEncoder。
@Bean
public static NoOpPasswordEncoder passwordEncoder() {
return NoOpPasswordEncoder.getInstance();
}
Spring為防止 跨站請求偽造(CSRF)
CSRF攻擊之所以可能是因為受害者網(wǎng)站的HTTP請求與攻擊者網(wǎng)站的請求完全相同击纬。這意味著無法拒絕來自邪惡網(wǎng)站的請求并允許來自銀行網(wǎng)站的請求鼎姐。為了防御CSRF攻擊,我們需要確保惡意站點(diǎn)無法提供請求中的某些內(nèi)容更振,因此我們可以區(qū)分這兩個請求炕桨。
Spring提供了兩種機(jī)制來防御CSRF攻擊:
- Specifying the SameSite Attribute on your session cookieSameSite屬性
同步器令牌模式
該解決方案是為了確保每個HTTP請求除了我們的會話cookie外,還必須在HTTP請求中包含一個安全的肯腕,隨機(jī)生成的值献宫,稱為CSRF令牌。
提交HTTP請求時实撒,服務(wù)器必須查找預(yù)期的CSRF令牌姊途,并將其與HTTP請求中的實際CSRF令牌進(jìn)行比較涉瘾。如果值不匹配,則應(yīng)拒絕HTTP請求捷兰。
讓我們看一下使用同步令牌模式時示例將如何變化立叛。假設(shè)實際的CSRF令牌必須位于名為的HTTP參數(shù)中_csrf
。
通常建議將該SameSite屬性用作深度防御贡茅,而不是針對CSRF攻擊的唯一防護(hù)秘蛇。
spring-security-core.jar
該模塊包含核心身份驗證和訪問控制類和接口,遠(yuǎn)程支持和基本配置API顶考。使用Spring Security的任何應(yīng)用程序都需要它赁还。它支持獨(dú)立的應(yīng)用程序,遠(yuǎn)程客戶端驹沿,方法(服務(wù)層)安全性和JDBC用戶配置艘策。
org.springframework.security.core
org.springframework.security.access
org.springframework.security.authentication
org.springframework.security.provisioning網(wǎng)絡(luò)-?spring-security-web.jar
該模塊包含過濾器和相關(guān)的Web安全基礎(chǔ)結(jié)構(gòu)代碼。它包含任何與Servlet API相關(guān)的內(nèi)容甚负。如果需要Spring Security Web認(rèn)證服務(wù)和基于URL的訪問控制spring-security-config.jar
該模塊包含安全名稱空間解析代碼和Java配置代碼柬焕。如果將Spring Security XML名稱空間用于配置或Spring Security的Java Configuration支持,則需要它梭域。
LDAP-?spring-security-ldap.jar
此模塊提供LDAP身份驗證和供應(yīng)代碼。如果您需要使用LDAP認(rèn)證或管理LDAP用戶條目搅轿,則此模塊提供LDAP身份驗證和供應(yīng)代碼病涨。如果您需要使用LDAP認(rèn)證或管理LDAP用戶條目,
spring-security-oauth2-core.jar包含為OAuth 2.0授權(quán)框架和OpenID Connect Core 1.0提供支持的核心類和接口璧坟。使用OAuth 2.0或OpenID Connect Core 1.0的應(yīng)用程序(例如客戶端既穆,資源服務(wù)器和授權(quán)服務(wù)器)需要它。OAuth 2.0客戶端-?spring-security-oauth2-client.jar
spring-security-oauth2-client.jar包含Spring Security對OAuth 2.0授權(quán)框架和OpenID Connect Core 1.0的客戶端支持雀鹃。使用OAuth 2.0登錄或OAuth客戶端支持的應(yīng)用程序需要使用它-
spring-security-oauth2-jose.jar包含Spring Security對JOSE(JavaScript對象簽名和加密)框架的支持幻工。
- JSON Web令牌(JWT)
- JSON Web簽名(JWS)
- JSON Web加密(JWE)
- JSON Web密鑰(JWK)
OAuth 2.0資源服務(wù)器-?spring-security-oauth2-resource-server.jar
spring-security-oauth2-resource-server.jar包含Spring Security對OAuth 2.0資源服務(wù)器的支持。它用于通過OAuth 2.0承載令牌保護(hù)API黎茎。ACL-?spring-security-acl.jar
該模塊包含專門的域?qū)ο驛CL實現(xiàn)囊颅。它用于將安全性應(yīng)用于應(yīng)用程序中的特定域?qū)ο髮嵗?/p>CAS —?spring-security-cas.jar
該模塊包含Spring Security的CAS客戶端集成。如果要對CAS單點(diǎn)登錄服務(wù)器使用Spring Security Web認(rèn)證傅瞻,則應(yīng)該使用它踢代。OpenID —?spring-security-openid.jar
該模塊包含OpenID Web身份驗證支持。它用于根據(jù)外部OpenID服務(wù)器對用戶進(jìn)行身份驗證嗅骄。頂級軟件包是org.springframework.security.openid胳挎。它需要OpenID4Java。
Servlet應(yīng)用
Spring Security通過使用標(biāo)準(zhǔn)Servlet與Servlet容器集成Filter溺森。這意味著它可以與在Servlet容器中運(yùn)行的任何應(yīng)用程序一起使用慕爬。
Servlet安全性:大局
“ 身份驗證”窑眯,“ 授權(quán)”和“防止利用漏洞”部分中建立了這種高級理解。
FilterChain
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) {
// do something before the rest of the application
chain.doFilter(request, response); // invoke the rest of the application
// do something after the rest of the application
}
DelegatingFilterProxy
DelegatingFilterProxy可以通過標(biāo)準(zhǔn)Servlet容器機(jī)制進(jìn)行注冊医窿,但是將所有工作委托給實現(xiàn)的Spring Bean Filter磅甩。
另一個好處DelegatingFilterProxy是,它允許延遲查找Filterbean實例留搔。這很重要更胖,因為容器需要Filter在容器啟動之前注冊實例。但是隔显,Spring通常使用a ContextLoaderListener來加載Spring Bean却妨,直到Filter需要注冊實例之后才能完成。
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) { // Lazily get Filter that was registered as a Spring Bean // For the example in [DelegatingFilterProxy](https://docs.spring.io/spring-security/site/docs/5.3.2.BUILD-SNAPSHOT/reference/html5/#servlet-delegatingfilterproxy-figure) `delegate` is an instance of *Bean Filter<sub>0</sub>* Filter delegate = getFilterBean(someBeanName); // delegate work to the Spring Bean delegate.doFilter(request, response); }
FilterChainProxy
Spring Security的Servlet支持包含在中FilterChainProxy
括眠。 FilterChainProxy
是Filter
Spring Security提供的一種特殊功能彪标,它允許Filter
通過委派許多實例SecurityFilterChain
。由于FilterChainProxy
是Bean掷豺,因此通常將其包裝在DelegatingFilterProxy中捞烟。
SecurityFilterChain
SecurityFilterChain
由FilterChainProxy用于確定Filter
應(yīng)對此請求調(diào)用哪些Spring Security 。
該保安過濾器中SecurityFilterChain
通常是豆類当船,但他們與注冊FilterChainProxy
代替的DelegatingFilterProxy题画。 FilterChainProxy
直接向Servlet容器或DelegatingFilterProxy注冊具有許多優(yōu)點(diǎn)。首先德频,它為Spring Security的所有Servlet支持提供了一個起點(diǎn)苍息。因此,如果您想對Spring Security的Servlet支持進(jìn)行故障排除壹置,則在其中添加調(diào)試點(diǎn)FilterChainProxy
是一個很好的起點(diǎn)竞思。
其次,由于FilterChainProxy
對于Spring Security的使用至關(guān)重要钞护,因此它可以執(zhí)行不被視為可選任務(wù)盖喷。例如,它清除SecurityContext
以避免內(nèi)存泄漏难咕。它還使用Spring Security HttpFirewall
來保護(hù)應(yīng)用程序免受某些類型的攻擊课梳。
另外,它在確定何時SecurityFilterChain
調(diào)用a時提供了更大的靈活性步藕。在Servlet容器中惦界,Filter
僅根據(jù)URL調(diào)用。但是咙冗,FilterChainProxy
可以HttpServletRequest
利用RequestMatcher
接口根據(jù)任何內(nèi)容確定調(diào)用沾歪。
實際上,FilterChainProxy
可以用來確定SecurityFilterChain
應(yīng)該使用哪個雾消。如果您的應(yīng)用程序可以為不同的片提供完全獨(dú)立的配置灾搏。
9.5挫望。安全過濾器
ChannelProcessingFilter
ConcurrentSessionFilter
WebAsyncManagerIntegrationFilter
SecurityContextPersistenceFilter
HeaderWriterFilter
CorsFilter
CsrfFilter
LogoutFilter
OAuth2AuthorizationRequestRedirectFilter
Saml2WebSsoAuthenticationRequestFilter
X509AuthenticationFilter
AbstractPreAuthenticatedProcessingFilter
CasAuthenticationFilter
OAuth2LoginAuthenticationFilter
Saml2WebSsoAuthenticationFilter
ConcurrentSessionFilter
OpenIDAuthenticationFilter
DefaultLoginPageGeneratingFilter
DefaultLogoutPageGeneratingFilter
BearerTokenAuthenticationFilter
RequestCacheAwareFilter
SecurityContextHolderAwareRequestFilter
JaasApiIntegrationFilter
RememberMeAuthenticationFilter
AnonymousAuthenticationFilter
OAuth2AuthorizationCodeGrantFilter
SessionManagementFilter
SwitchUserFilter
處理安全異常
在ExceptionTranslationFilter
允許的翻譯AccessDeniedException
和AuthenticationException
到HTTP響應(yīng)。
ExceptionTranslationFilter
作為安全過濾器之一插入到FilterChainProxy中狂窑。
-
1號
ExceptionTranslationFilter
調(diào)用FilterChain.doFilter(request, response)
將調(diào)用應(yīng)用程序的其余部分。 -
[圖片上傳失敗...(image-9e46a-1586791805902)] 如果用戶未通過身份驗證或為
AuthenticationException
泉哈,則Start Authentication.將
HttpServletRequest
保存在中RequestCache
蛉幸。當(dāng)用戶成功驗證身份后,將RequestCache
用于重播原始請求丛晦。的
AuthenticationEntryPoint
用于從客戶機(jī)請求的憑證奕纫。例如,它可能重定向到登錄頁面或發(fā)送WWW-Authenticate
標(biāo)題烫沙。
-
3號
AccessDeniedException
,則拒絕訪問锌蓄。將AccessDeniedHandler
被調(diào)用升筏,以拒絕提手接近。
| |
如果應(yīng)用程序未拋出AccessDeniedException
或AuthenticationException
瘸爽,ExceptionTranslationFilter
則不執(zhí)行任何操作
ExceptionTranslationFilter偽代碼
try {
filterChain.doFilter(request, response);
} catch (AccessDeniedException | AuthenticationException e) {
if (!authenticated || e instanceof AuthenticationException) {
startAuthentication();
} else {
accessDenied();
}
}
| | 你可以從召回進(jìn)展的Filter
小號即調(diào)用FilterChain.doFilter(request, response)
是等效的調(diào)用應(yīng)用程序的其余部分您访。這意味著如果應(yīng)用程序的另一部分(即FilterSecurityInterceptor
方法安全性)拋出AuthenticationException
或AccessDeniedException
,它將在此處被捕獲和處理剪决。 |
| | 如果用戶未通過身份驗證或為AuthenticationException
洋只,則開始身份驗證。 |
| | 否則昼捍,訪問被拒絕 |