Security中的WebSecurityConfigurerAdapter詳解
本文來詳細(xì)說下security中的WebSecurityConfigurerAdapter
概述
今天我們要進(jìn)一步的的學(xué)習(xí)如何自定義配置 Spring Security 我們已經(jīng)多次提到了 WebSecurityConfigurerAdapter ,而且我們知道 Spring Boot 中的自動配置實(shí)際上是通過自動配置包下的 SecurityAutoConfiguration 總配置類上導(dǎo)入的 Spring Boot Web 安全配置類 SpringBootWebSecurityConfiguration 來配置的。
SpringBootWebSecurityConfiguration源碼
package org.springframework.boot.autoconfigure.security.servlet; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication; import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication.Type; import org.springframework.context.annotation.Configuration; import org.springframework.core.annotation.Order; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; @Configuration( proxyBeanMethods = false ) @ConditionalOnClass({WebSecurityConfigurerAdapter.class}) @ConditionalOnMissingBean({WebSecurityConfigurerAdapter.class}) @ConditionalOnWebApplication( type = Type.SERVLET ) public class SpringBootWebSecurityConfiguration { public SpringBootWebSecurityConfiguration() { } @Configuration( proxyBeanMethods = false ) @Order(2147483642) static class DefaultConfigurerAdapter extends WebSecurityConfigurerAdapter { DefaultConfigurerAdapter() { } } }
常用方法
WebSecurityConfigurerAdapter類圖
常用配置
下面貼一下WebSecurityConfigurerAdapter在項(xiàng)目中的常用配置
package cn.wideth.framework.config; import cn.wideth.framework.security.handle.AuthenticationEntryPointImpl; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.http.HttpMethod; import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.builders.WebSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; import org.springframework.security.config.http.SessionCreationPolicy; import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; import org.springframework.security.web.authentication.logout.LogoutFilter; import org.springframework.web.filter.CorsFilter; import cn.wideth.framework.security.filter.JwtAuthenticationTokenFilter; import cn.wideth.framework.security.handle.LogoutSuccessHandlerImpl; /** * spring security配置 * */ @EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true) public class SecurityConfig extends WebSecurityConfigurerAdapter { /** * 自定義用戶認(rèn)證邏輯 */ @Autowired private UserDetailsService userDetailsService; /** * 認(rèn)證失敗處理類 */ @Autowired private AuthenticationEntryPointImpl unauthorizedHandler; /** * 退出處理類 */ @Autowired private LogoutSuccessHandlerImpl logoutSuccessHandler; /** * token認(rèn)證過濾器 */ @Autowired private JwtAuthenticationTokenFilter authenticationTokenFilter; /** * 跨域過濾器 */ @Autowired private CorsFilter corsFilter; /** * 解決 無法直接注入 AuthenticationManager * * @return * @throws Exception */ @Bean @Override public AuthenticationManager authenticationManagerBean() throws Exception { return super.authenticationManagerBean(); } /** * 強(qiáng)散列哈希加密實(shí)現(xiàn) */ @Bean public BCryptPasswordEncoder bCryptPasswordEncoder() { return new BCryptPasswordEncoder(); } /** * 身份認(rèn)證接口 */ @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { //在這里關(guān)聯(lián)數(shù)據(jù)庫和security auth.userDetailsService(userDetailsService).passwordEncoder(bCryptPasswordEncoder()); } /** * anyRequest | 匹配所有請求路徑 * access | SpringEl表達(dá)式結(jié)果為true時(shí)可以訪問 * anonymous | 匿名可以訪問 * denyAll | 用戶不能訪問 * fullyAuthenticated | 用戶完全認(rèn)證可以訪問(非remember-me下自動登錄) * hasAnyAuthority | 如果有參數(shù),參數(shù)表示權(quán)限,則其中任何一個(gè)權(quán)限可以訪問 * hasAnyRole | 如果有參數(shù),參數(shù)表示角色,則其中任何一個(gè)角色可以訪問 * hasAuthority | 如果有參數(shù),參數(shù)表示權(quán)限,則其權(quán)限可以訪問 * hasIpAddress | 如果有參數(shù),參數(shù)表示IP地址,如果用戶IP和參數(shù)匹配,則可以訪問 * hasRole | 如果有參數(shù),參數(shù)表示角色,則其角色可以訪問 * permitAll | 用戶可以任意訪問 * rememberMe | 允許通過remember-me登錄的用戶訪問 * authenticated | 用戶登錄后可訪問 */ @Override protected void configure(HttpSecurity httpSecurity) throws Exception { httpSecurity // CSRF禁用,因?yàn)椴皇褂胹ession .csrf().disable() // 認(rèn)證失敗處理類 .exceptionHandling().authenticationEntryPoint(unauthorizedHandler).and() // 基于token,所以不需要session .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and() // 過濾請求 .authorizeRequests() // 對于登錄login 驗(yàn)證碼captchaImage 允許匿名訪問 .antMatchers("/login", "/captchaImage").anonymous() .antMatchers( HttpMethod.GET, "/*.html", "/**/*.html", "/**/*.css", "/**/*.js" ).permitAll() .antMatchers("/profile/**").permitAll() .antMatchers("/common/download**").permitAll() .antMatchers("/common/download/resource**").permitAll() .antMatchers("/swagger-ui.html").permitAll() .antMatchers("/swagger-resources/**").permitAll() .antMatchers("/webjars/**").permitAll() .antMatchers("/*/api-docs").permitAll() .antMatchers("/druid/**").permitAll() .antMatchers("/flowable/**").permitAll() .antMatchers("/socket/**").permitAll() .antMatchers("/api/common/**").permitAll() .antMatchers("/api/contract/**").permitAll() .antMatchers("/api/project/**").permitAll() .antMatchers("/api/document/**").permitAll() .antMatchers("/api/purchase/**").permitAll() // 除上面外的所有請求全部需要鑒權(quán)認(rèn)證 .anyRequest().authenticated() .and() .headers().frameOptions().disable(); httpSecurity.logout().logoutUrl("/logout").logoutSuccessHandler(logoutSuccessHandler); // 添加JWT filter httpSecurity.addFilterBefore(authenticationTokenFilter, UsernamePasswordAuthenticationFilter.class); // 添加CORS filter httpSecurity.addFilterBefore(corsFilter, JwtAuthenticationTokenFilter.class); httpSecurity.addFilterBefore(corsFilter, LogoutFilter.class); } /*** * 核心過濾器配置方法 * @param web * @throws Exception */ @Override public void configure(WebSecurity web) throws Exception { super.configure(web); } }
相信已經(jīng)有人注意到了上面 WebSecurityConfigurerAdapter 中我覆寫(@Override)了三個(gè)configure方法,我們一般會通過自定義配置這三個(gè)方法來自定義我們的安全訪問策略。
認(rèn)證管理器配置方法
AuthenticationManagerBuilder(身份驗(yàn)證管理生成器)
void configure(AuthenticationManagerBuilder auth) 用來配置認(rèn)證管理器AuthenticationManager。說白了就是所有 UserDetails 相關(guān)的它都管,包含 PasswordEncoder 密碼等。如果你不清楚可以通過 Spring Security 中的 UserDetail 進(jìn)行了解。本文對 AuthenticationManager 不做具體分析講解,后面會有專門的文章來講這個(gè)東西 。
常見用法
/** * 身份認(rèn)證接口 */ @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { auth.userDetailsService(userDetailsService).passwordEncoder(bCryptPasswordEncoder()); }
核心過濾器配置方法
WebSecurity(WEB安全)
void configure(WebSecurity web) 用來配置 WebSecurity 。而 WebSecurity 是基于 Servlet Filter 用來配置 springSecurityFilterChain 。而 springSecurityFilterChain 又被委托給了 Spring Security 核心過濾器 Bean DelegatingFilterProxy 。 相關(guān)邏輯你可以在 WebSecurityConfiguration 中找到。我們一般不會過多來自定義 WebSecurity , 使用較多的使其ignoring() 方法用來忽略 Spring Security 對靜態(tài)資源的控制。
安全過濾器鏈配置方法
HttpSecurity(HTTP請求安全處理)
void configure(HttpSecurity http) 這個(gè)是我們使用最多的,用來配置 HttpSecurity 。 HttpSecurity 用于構(gòu)建一個(gè)安全過濾器鏈 SecurityFilterChain 。SecurityFilterChain 最終被注入核心過濾器 。 HttpSecurity 有許多我們需要的配置。我們可以通過它來進(jìn)行自定義安全訪問策略。所以我們單獨(dú)開一章來講解這個(gè)東西。
HttpSecurity 配置
HttpSecurity 是后面幾篇文章的重點(diǎn),我們將實(shí)際操作它來實(shí)現(xiàn)一些實(shí)用功能。所以本文要著重介紹它。
HttpSecurity 類圖
默認(rèn)配置
默認(rèn)配置
protected void configure(HttpSecurity http) throws Exception { this.logger.debug("Using default configure(HttpSecurity). If subclassed this will potentially override subclass configure(HttpSecurity)."); ((HttpSecurity)((HttpSecurity((AuthorizedUrl) http. authorizeRequests(). anyRequest()).authenticated(). and()). formLogin(). and()). httpBasic(); }
上面是 Spring Security 在 Spring Boot 中的默認(rèn)配置。通過以上的配置,你的應(yīng)用具備了一下的功能:
- 所有的請求訪問都需要被授權(quán)。
- 使用 form 表單進(jìn)行登陸(默認(rèn)路徑為/login),也就是前幾篇我們見到的登錄頁。
- 防止 CSRF 攻擊、 XSS 攻擊。
- 啟用 HTTP Basic 認(rèn)證
常用方法解讀
HttpSecurity 使用了builder 的構(gòu)建方式來靈活制定訪問策略。最早基于 XML 標(biāo)簽對 HttpSecurity 進(jìn)行配置?,F(xiàn)在大部分使用 javaConfig方式。常用的方法解讀如下:
方法 | 說明 |
---|---|
openidLogin() | 用于基于 OpenId 的驗(yàn)證 |
headers() | 將安全標(biāo)頭添加到響應(yīng),比如說簡單的 XSS 保護(hù) |
cors() | 配置跨域資源共享( CORS ) |
sessionManagement() | 允許配置會話管理 |
portMapper() | 允許配置一個(gè)PortMapper(HttpSecurity#(getSharedObject(class))),其他提供SecurityConfigurer的對象使用 PortMapper 從 HTTP 重定向到 HTTPS 或者從 HTTPS 重定向到 HTTP。默認(rèn)情況下,Spring Security使用一個(gè)PortMapperImpl映射 HTTP 端口8080到 HTTPS 端口8443,HTTP 端口80到 HTTPS 端口443 |
jee() | 配置基于容器的預(yù)認(rèn)證。 在這種情況下,認(rèn)證由Servlet容器管理 |
x509() | 配置基于x509的認(rèn)證 |
rememberMe() | 允許配置“記住我”的驗(yàn)證 |
authorizeRequests() | 允許基于使用HttpServletRequest限制訪問 |
requestCache() | 允許配置請求緩存 |
exceptionHandling() | 允許配置錯(cuò)誤處理 |
securityContext() | 在HttpServletRequests之間的SecurityContextHolder上設(shè)置SecurityContext的管理。 當(dāng)使用WebSecurityConfigurerAdapter時(shí),這將自動應(yīng)用 |
servletApi() | 將HttpServletRequest方法與在其上找到的值集成到SecurityContext中。 當(dāng)使用WebSecurityConfigurerAdapter時(shí),這將自動應(yīng)用 |
csrf() | 添加 CSRF 支持,使用WebSecurityConfigurerAdapter時(shí),默認(rèn)啟用 |
logout() | 添加退出登錄支持。當(dāng)使用WebSecurityConfigurerAdapter時(shí),這將自動應(yīng)用。默認(rèn)情況是,訪問URL”/ logout”,使HTTP Session無效來清除用戶,清除已配置的任何#rememberMe()身份驗(yàn)證,清除SecurityContextHolder,然后重定向到”/login?success” |
anonymous() | 允許配置匿名用戶的表示方法。 當(dāng)與WebSecurityConfigurerAdapter結(jié)合使用時(shí),這將自動應(yīng)用。 默認(rèn)情況下,匿名用戶將使用org.springframework.security.authentication.AnonymousAuthenticationToken表示,并包含角色 “ROLE_ANONYMOUS” |
formLogin() | 指定支持基于表單的身份驗(yàn)證。如果未指定FormLoginConfigurer#loginPage(String),則將生成默認(rèn)登錄頁面 |
oauth2Login() | 根據(jù)外部OAuth 2.0或OpenID Connect 1.0提供程序配置身份驗(yàn)證 |
requiresChannel() | 配置通道安全。為了使該配置有用,必須提供至少一個(gè)到所需信道的映射 |
httpBasic() | 配置 Http Basic 驗(yàn)證 |
addFilterBefore() | 在指定的Filter類之前添加過濾器 |
addFilterAt() | 在指定的Filter類的位置添加過濾器 |
addFilterAfter() | 在指定的Filter類的之后添加過濾器 |
and() | 連接以上策略的連接器,用來組合安全策略。實(shí)際上就是"而且"的意思 |
本文小結(jié)
本文詳細(xì)介紹了WebSecurityConfigurerAdapter相關(guān)的知識與內(nèi)容,后續(xù)會對HttpSecurity相關(guān)的知識進(jìn)行詳細(xì)介紹,這個(gè)也是在平時(shí)的開發(fā)中使用的最多的地方。
到此這篇關(guān)于Security中的WebSecurityConfigurerAdapter詳解的文章就介紹到這了,更多相關(guān)WebSecurityConfigurerAdapter詳解內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Java中synchronized關(guān)鍵字引出的多種鎖 問題
synchronized關(guān)鍵字是JAVA中常用的同步功能,提供了簡單易用的鎖功能。這篇文章主要介紹了Java中synchronized關(guān)鍵字引出的多種鎖問題,需要的朋友可以參考下2019-07-07SpringCloud客戶端的負(fù)載均衡Ribbon的實(shí)現(xiàn)
微服務(wù)架構(gòu),不可避免的存在單個(gè)微服務(wù)有多個(gè)實(shí)例,這篇文章主要介紹了SpringCloud客戶端的負(fù)載均衡Ribbon的實(shí)現(xiàn),小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2018-06-06如何使用pipeline和jacoco獲取自動化測試代碼覆蓋率
這篇文章主要介紹了如何使用pipeline和jacoco獲取自動化測試代碼覆蓋率,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-11-11初次使用IDEA創(chuàng)建maven項(xiàng)目的教程
這篇文章主要介紹了初次使用IDEA創(chuàng)建maven項(xiàng)目的教程講解,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下2018-01-01