使用Spring Boot與Spring MVC進(jìn)行Web開發(fā)時,如果項(xiàng)目引入spring-boot- starter-security依賴啟動器,MVC Security 安全管理功能就會自動生效,其默認(rèn)的安全配置是在SecurityAutoConfiguration和UserDetailsServiceAutoConfiguration中實(shí)現(xiàn)的。其中,SecurityAutoConfiguration會導(dǎo)入并自動化配置SpringBootWebSecurityConfiguration用于啟動Web安全管理,UserDetailsServiceAutoConfiguration則用于配置用戶身份信息。
通過自定義WebSecurityConfigurerAdapter 類型的Bean組件,可以完全關(guān)閉Security 提供的Web應(yīng)用默認(rèn)安全配置,但是不會關(guān)閉UserDetailsService用戶信息自動配置類。如果要關(guān)閉UserDetailsService默認(rèn)用戶信息配置,可以自定義UserDetailsService、AuthenticationProvider或AuthenticationManager類型的Bean組件。另外,可以通過自定義WebSecurityConfigurerAdapter類型的Bean組件覆蓋默認(rèn)訪問規(guī)則。Spring Boot 提供了非常多方便的方法,可用于覆蓋請求映射和靜態(tài)資源的訪問規(guī)則。
下面我們通過Spring Security API查看WebSecurityConfigurerAdapter的主要方法,具體所示:
configure(AuthenticationManagerBuilder auth):定制用戶認(rèn)證管理器來實(shí)現(xiàn)用戶認(rèn)證
configure(HttpSecurity http):定制基于HTTP請求的用戶訪問控制
從上面可以看到,WebSecurityConfigurerAdapter類中包含兩個非常重要的配置方法,分別是configure(AuthenticationManagerBuilder auth)和configure(HttpSecurity http)。Configure(AuthenticationManagerBuilder auth)方法用于構(gòu)建認(rèn)證管理器,configure(HttpSecurity http)方法用于對基于HTTP的請求進(jìn)行請求訪問控制。
一、自定義用戶認(rèn)證:
通過自定義WebSecurityConfigurerAdapter類型的Bean組件,并重寫configure(AuthenticationManagerBuilder auth)方法,可以自定義用戶認(rèn)證。針對自定義用戶認(rèn)證,Spring Security提供了多種自定義認(rèn)證方式, 包括有: In-Memory Authentication (內(nèi)存 身份認(rèn)證)、JDBCAuthentication ( JDBC身份認(rèn)證)、LDAP Authentication ( LDAP身份認(rèn)證)、AuthenticationProvider (身份認(rèn)證提供商)和UserDetailsService (身份詳情服務(wù))。 下面我們選取其中3個比較有代表性的方式講解如何實(shí)現(xiàn)自定義用戶認(rèn)證。
二、自定義用戶授權(quán)管理:
當(dāng)一個系統(tǒng)建立之后,通常需要適當(dāng)?shù)刈鲆恍?quán)限控制,使得不同用戶具有不同的權(quán)限操作系統(tǒng)。例如,一般的項(xiàng)目中都會做一些簡單的登錄控制,只有特定用戶才能登錄訪問。接下來我們針對Web應(yīng)用中常見的自定義用戶授權(quán)管理進(jìn)行介紹。
自定義用戶訪問控制:
實(shí)際生產(chǎn)中,網(wǎng)站訪問多是基于HTTP請求的,上面MVC Security 安全配置介紹時,我們已經(jīng)分析出通過重寫WebSecurityConfigurerAdapter類的configure(HttpSecurity http)方法可以對基于HTTP的請求訪問進(jìn)行控制。下面我們通過對configure(HttpSecurity http)方法剖析,分析自定義用戶訪問控制的實(shí)現(xiàn)過程。
configure(HttpSecurity http)方法的參數(shù)類型是HttpSecurity類,HttpSecurity類提供了Http請求的限制以及權(quán)限、Session 管理配置、CSRF跨站請求問題等方法,具體如下所示。
HttpSecurity 類的主要方法及說明:
authorizeRequests():開啟基于HtpSereleRequest請求訪問的限制
formLogin():開啟基于表單的用戶登錄
httpBasic():開啟基于HTTP請求的Basic認(rèn)證登錄
logout():開啟退出登錄的支持
sessionManagement():開啟Session管理配置
rememberMe():開啟記住我功能
csrf():配置CSRF跨站請求偽造防護(hù)功能
此處重點(diǎn)講解用戶訪問控制,這里先對authorizeRequests()方法的返回值做進(jìn)一步查看,其中涉及用戶訪問控制的主要方法及說明如下所示。
antMatchers(java.lang.String .. antPatterns):開啟Ant風(fēng)格的路徑匹配
mvcMatchers(java.lang. String ... patterns):開啟MVC風(fēng)格的路徑匹配(與Ant風(fēng)格類似)
regexMatchers(java.lang String... regexPatterns):開啟正則表達(dá)式的路徑匹配
and():功能連接符
anyRequest():匹配任何請求
rememberMe():開啟記住我功能
access(String attribute):匹配給定的SpEL表達(dá)式計算結(jié)果是否為true
hasAnyRole(String .. roles):匹配用戶是否有參數(shù)中的任意角色
hasRole(String role):匹配用戶是否有某一個角色
hasAnyAuthority(String .. authorities):匹配用戶是否有參數(shù)中的任意權(quán)限
hasAuthority(String authority):匹配用戶是否有某一個權(quán)限
authenticated():匹配已經(jīng)登錄認(rèn)證的用戶
fullyAuthenticated():匹配完整登錄認(rèn)證的用戶(非rememberMe登錄用戶)
haslpAddress(String ipaddressExpression):匹配某IP地址的訪問請求
permitAll():無條件對請求進(jìn)行放行
上面列舉了用戶請求訪問的常用方法,如果想了解更多方法可以通過查看API文檔。
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
// 授權(quán)
http.authorizeRequests()
.antMatchers(
"/user/setting",
"/user/upload",
"/discuss/add",
"/comment/add/**",
"/letter/**",
"/notice/**",
"/like",
"/follow",
"/unfollow"
)
.hasAnyAuthority(
"AUTHORITY_USER",
"AUTHORITY_ADMIN",
"AUTHORITY_MODERATOR"
)
.antMatchers(
"/discuss/top",
"/discuss/wonderful"
)
.hasRole("AUTHORITY_USER")
.anyRequest().permitAll()
.and()
.formLogin();
}
}
自定義用戶登錄:
formLogin()是開啟基于表單的用戶登錄,所以下面就圍繞formLogin()這個方法來探索并講解自定義登錄的具體實(shí)現(xiàn)。
用戶登錄相關(guān)的主要方法及說明如下所示。
loginPage(String loginPage):用戶登錄頁面跳轉(zhuǎn)路徑,默認(rèn)為get請求的/login
successForwardUrl(String forwardUrl):用戶登錄成功后的重定向地址
successHandler(AuthenticationSuccessHandler?successHandler):用戶登錄成功后的處理
defaultSuccessUrl(String defaultSuccessUrl):用戶直接登錄后默認(rèn)跳轉(zhuǎn)地址
failureForwardUrl(String forwardUrl):用戶登錄失敗后的重定向地址
failureUrl(String authenticationFailureUrl):用戶登錄失敗后的跳轉(zhuǎn)地址,默認(rèn)為/login?error
failureHandler(AuthenticationF ailureHandler?authenticationF ailureHandler):用戶登錄失敗后的錯誤處理
usernameParameter(String usernameParameter):登錄用戶的用戶名參數(shù),默認(rèn)為username
passwordParameter(String passwordParameter):登錄用戶的密碼參數(shù),默認(rèn)為password
loginProcessingUrl(String loginProcessingUr):登錄表單提交的路徑,默認(rèn)為post請求的login
permitAIl():無條件對請求進(jìn)行放行
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
// 自定義用戶登錄控制
http.formLogin()
.loginPage("/userLogin").permitAll()
.usernameParameter("name").passwordParameter("pwd")
.defaultSuccessUrl("/")
.failureUrl("/userLogin?error");
}
}
自定義用戶退出:
自定義用戶退出主要考慮退出后的會話如何管理以及跳轉(zhuǎn)到哪個頁面。HttpSecurity 類的logout()方法用來處理用戶退出,它默認(rèn)處理路徑為“l(fā)ogout”的Post類型請求,同時也會清除Session和“Remember Me”(記住我)等任何默認(rèn)用戶配置。下面我們就圍繞logout)這個方法來探索并講解自定義用戶退出的具體實(shí)現(xiàn)。
logout()方法中涉及用戶退出的主要方法及說明如下所示。
logoutUrI(String logoutUrl):用戶退出處理控制URL,默認(rèn)為post請求的logout
logoutSuccessUrl(String logoutSuccessUrI) :用戶退出成功后的重定向地址
logoutSuccessHandler(LogoutSuccessHandle?logoutSuccessHandler):用戶退出成功后的處理器設(shè)置
deleteCookies(String ... cookieNamesToClear):用戶退出后刪除指定Cookie
invalidateHttpSession(boolean invalidateHttpSession):用戶退出后是否立即清除Session (默認(rèn)為true )
clearAuthentication(boolean clearAuthentication):用戶退出后是否立即清除Authentication用戶認(rèn)證信息(默認(rèn)為true)
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
// 自定義用戶退出控制
http.logout()
.logoutUrlUrl("/mylogout")
.logoutSuccessUrl("/");
}
}
記住我功能:
在實(shí)際開發(fā)中,有些項(xiàng)目為了用戶登錄方便還會提供記住我( Remember-Me )功能。如果用戶登錄時勾選了記住我選項(xiàng),那么在一段有效時間內(nèi),會默認(rèn)自動登錄,并允許訪問相關(guān)頁面,這就免去了重復(fù)登錄操作的麻煩。Spring Security提供了用戶登錄控制的同時,當(dāng)然也提供了對應(yīng)的記住我功能,前面介紹的HttpSecurity類的主要方法rememberMe()就是Spring Security 用來處理記住我功能的。下面我們圍繞rememberMe()這個方法來探索并講解記住我功能的具體實(shí)現(xiàn)。
rememberMe()記住我功能相關(guān)涉及記住我的主要方法及說明如下所示。
rememberMeParameter(String rememberMeParameter):指示在登錄時記住用戶的HTTP參數(shù)
key(String key):記住我認(rèn)證生成的Token令牌標(biāo)識
tokenValiditySeconds(int tokenValiditySeconds):記住我Token令牌有效期,單位為s (秒)
tokenRepository(PersistentTokenRepository tokenRepository):指定要使用的PersistentTokenRepository,用來配置持久化Token令牌
alwaysRemember(boolean alwaysRemember):是否應(yīng)該始終創(chuàng)建記住我Cookie,默認(rèn)為false
clearAuthentication(boolean clearAuthentication):是否設(shè)置Cookie為安全的,如果設(shè)置為true,則必須通過HTTPS進(jìn)行連接請求
需要說明的是,Spring Security 針對記住我功能提供了兩種實(shí)現(xiàn):一種是簡單地使用加密來保證基于Cookie中Token的安全;另一種是通過數(shù)據(jù)庫或其他持久化機(jī)制來保存生成的Token。下面我們分別對這兩種記住我功能的實(shí)現(xiàn)進(jìn)行講解并演示說明。
基于簡單加密Token 的方式:
基于簡單加密Token的方式實(shí)現(xiàn)記住我功能非常簡單,當(dāng)用戶選擇記住我并成功登錄后,Spring Security將會生成一個Cookie并發(fā)送給客戶端瀏覽器。
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
// 定制Remember-Me記住我功能
http.rememberMe()
.rememberMeParameter("rememberme")
.tokenValiditySeconds(200);
}
}
基于持久化Token的方式:
持久化Token的方式與簡單加密Token的方式在實(shí)現(xiàn)Remember -Me功能上大體相同,都是在用戶選擇[記住我]并成功登錄后,將生成的Token存入Cookie中并發(fā)送到客戶端瀏覽器,在下次用戶通過同一客戶端訪問系統(tǒng)時,系統(tǒng)將直接從客戶端Cookie中讀取Token進(jìn)行認(rèn)證。兩者的主要區(qū)別在于:基于簡單加密Token的方式,生成的Token將在客戶端保存一段時間,如果用戶不退出登錄,或者不修改密碼,那么在Cookie失效之前,任何人都可以無限制地使用該Token進(jìn)行自動登錄;而基于持久化Token的方式采用如下實(shí)現(xiàn)邏輯。
- 用戶選擇[記住我]成功登錄后,Security會把username、隨機(jī)產(chǎn)生的序列號、生成的Token進(jìn)行持久化存儲(例如一個數(shù)據(jù)表中),同時將它們的組合生成一個 Cookie發(fā)送給客戶端瀏覽器。
- 當(dāng)用戶再次訪問系統(tǒng)時,首先檢查客戶端攜帶的Cookie,如果對應(yīng)Cookie 中包含的username、序列號和Token與數(shù)據(jù)庫中保存的一致,則通過驗(yàn)證并自動登錄,同時系統(tǒng)將重新生成一個新的Token替換數(shù)據(jù)庫中舊的Token,并將新的Cookie再次發(fā)送給客戶端。
- 如果Cookie中的Token不匹配,則很有可能是用戶的Cookie被盜用了。由于盜用者使用初次生成的Token進(jìn)行登錄時會生成一個新的 Token,所以當(dāng)用戶在不知情時再次登錄就會出現(xiàn)Token不匹配的情況,這時就需要重新登錄,并生成新的Token和Cookie。同時Spring?Security就可以發(fā)現(xiàn)Cookie可能被盜用的情況,它將刪除數(shù)據(jù)庫中與當(dāng)前用戶相關(guān)的所有Token記錄,這樣盜用者使用原有的Cookie將不能再次登錄。
- 如果用戶訪問系統(tǒng)時沒有攜帶Cookie, 或者包含的username和序列號與數(shù)據(jù)庫中保存的不-致,那么將會引導(dǎo)用戶到登錄頁面。
從以上實(shí)現(xiàn)邏輯可以看出,持久化Token的方式比簡單加密Token的方式相對更加安全。使用簡單加密Token的方式,一旦用戶的Cookie被盜用,在Token有效期內(nèi),盜用者可以無限制地自動登錄進(jìn)行惡意操作,直到用戶本人發(fā)現(xiàn)并修改密碼才會避免這種問題;而使用持久化Token的方式相對安全,用戶每登錄一次都會生成新的Token和Cookie,但也給盜用者留下了在用戶進(jìn)行第2次登錄前進(jìn)行惡意操作的機(jī)會,只有在用戶進(jìn)行第2次登錄并更新Token和Cookie時,才會避免這種問題。因此,總體來講,對于安全性要求很高的應(yīng)用,不推薦使用Remember -Me功能。
CSRF防護(hù)功能:
CSRF (Cross-site request forgery,跨站請求偽造),也被稱為“One Click Attack”(一鍵攻擊)或者”Session Riding” (會話控制),通常縮寫為CSRF或者XSRF,是一種對網(wǎng)站的惡意利用。與傳統(tǒng)的XSS攻擊( Cross-site Scriping,跨站腳本攻擊)相比,CSRF攻擊更加難以防范,被認(rèn)為比XSS更具危險性。CSRF攻擊可以在受害者毫不知情的情況下以受害者的名義偽造請求發(fā)送給攻擊頁面,從而在用戶未授權(quán)的情況下執(zhí)行在權(quán)限保護(hù)之下的操作。
例如,一個用戶Tom登錄銀行站點(diǎn)服務(wù)器準(zhǔn)備進(jìn)行轉(zhuǎn)賬操作,在此用戶信息有效期內(nèi),Tom
被誘導(dǎo)查看了一個黑客惡意網(wǎng)站,該網(wǎng)站就會獲取到Tom登錄后的瀏覽器與銀行網(wǎng)站之間尚未過期的Session信息,而Tom瀏覽器的Cookie中含有Tom銀行賬戶的認(rèn)證信息,此時黑客就會偽裝成Tom認(rèn)證后的合法用戶對銀行賬戶進(jìn)行非法操作。
在討論如何抵御CSRF攻擊之前,先要明確CSRF攻擊的對象,也就是要保護(hù)的對象。從上
面的例子可知,CSRF 攻擊是黑客借助受害者的Cookie騙取服務(wù)器的信任,但是黑客并不能獲取Cookie,也看不到Cookie 的具體內(nèi)容。另外,對于服務(wù)器返回的結(jié)果,由于瀏覽器同源策略的限制,黑客無法進(jìn)行解析。黑客所能做的就是偽造正常用戶給服務(wù)器發(fā)送請求,以執(zhí)行請求中所描述的命令,在服務(wù)器端直接改變數(shù)據(jù)的值,而非竊取服務(wù)器中的數(shù)據(jù)。因此,針對CSRF攻擊要保護(hù)的對象是那些可以直接產(chǎn)生數(shù)據(jù)變化的服務(wù),而對于讀取數(shù)據(jù)的服務(wù),可以不進(jìn)行CSRF保護(hù)。例如,銀行轉(zhuǎn)賬操作會改變賬號金額,需要進(jìn)行CSRF保護(hù)。獲取銀行卡等級信息是讀取操作,不會改變數(shù)據(jù),可以不需要保護(hù)。在業(yè)界目前防御CSRF攻擊主要有以下3種策略。
(1)驗(yàn)證HTTP Referer字段。
(2)在請求地址中添加Token并驗(yàn)證。
(3)在HTTP頭中自定義屬性并驗(yàn)證。
Spring Security安全框架提供了CSRF防御相關(guān)方法,具體如下所示。
disable():關(guān)閉Security默認(rèn)開啟的CSRF防御功能
csrfTokenRepository(CsrfTokenRepositor?csrfTokenRepository):指定要使用的CsrfTokenRepository ( Token令牌持久化倉庫)。默認(rèn)是由LazyCsrfTokenRepository包裝的HttpSessionCsrfTokenRepository文章來源:http://www.zghlxwxcb.cn/news/detail-605807.html
rgurerProtetionatchereqestMatcher?requireCSsrfProtectionMatcher):指定針對什么類型的請求應(yīng)用CSRF防護(hù)功能。默認(rèn)設(shè)置是忽略GET、HEAD、TRACE和OPTIONS請求,而處理并防御其他所有請求文章來源地址http://www.zghlxwxcb.cn/news/detail-605807.html
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
// 可以關(guān)閉Spring Security默認(rèn)開啟的CSRF防護(hù)功能
http.csrf().disable();;
}
}
到了這里,關(guān)于Spring Security安全配置的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!