Security中的WebSecurityConfigurerAdapter詳解
本文來詳細(xì)說下security中的WebSecurityConfigurerAdapter
概述
今天我們要進(jìn)一步的的學(xué)習(xí)如何自定義配置 Spring Security 我們已經(jīng)多次提到了 WebSecurityConfigurerAdapter ,而且我們知道 Spring Boot 中的自動(dòng)配置實(shí)際上是通過自動(dòng)配置包下的 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 | 匹配所有請(qǐng)求路徑
* access | SpringEl表達(dá)式結(jié)果為true時(shí)可以訪問
* anonymous | 匿名可以訪問
* denyAll | 用戶不能訪問
* fullyAuthenticated | 用戶完全認(rèn)證可以訪問(非remember-me下自動(dòng)登錄)
* 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()
// 過濾請(qǐng)求
.authorizeRequests()
// 對(duì)于登錄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()
// 除上面外的所有請(qǐng)求全部需要鑒權(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方法,我們一般會(huì)通過自定義配置這三個(gè)方法來自定義我們的安全訪問策略。
認(rèn)證管理器配置方法
AuthenticationManagerBuilder(身份驗(yàn)證管理生成器)
void configure(AuthenticationManagerBuilder auth) 用來配置認(rèn)證管理器AuthenticationManager。說白了就是所有 UserDetails 相關(guān)的它都管,包含 PasswordEncoder 密碼等。如果你不清楚可以通過 Spring Security 中的 UserDetail 進(jìn)行了解。本文對(duì) AuthenticationManager 不做具體分析講解,后面會(huì)有專門的文章來講這個(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 中找到。我們一般不會(huì)過多來自定義 WebSecurity , 使用較多的使其ignoring() 方法用來忽略 Spring Security 對(duì)靜態(tài)資源的控制。
安全過濾器鏈配置方法
HttpSecurity(HTTP請(qǐng)求安全處理)
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)用具備了一下的功能:
- 所有的請(qǐng)求訪問都需要被授權(quán)。
- 使用 form 表單進(jìn)行登陸(默認(rèn)路徑為/login),也就是前幾篇我們見到的登錄頁。
- 防止 CSRF 攻擊、 XSS 攻擊。
- 啟用 HTTP Basic 認(rèn)證
常用方法解讀
HttpSecurity 使用了builder 的構(gòu)建方式來靈活制定訪問策略。最早基于 XML 標(biāo)簽對(duì) HttpSecurity 進(jìn)行配置?,F(xiàn)在大部分使用 javaConfig方式。常用的方法解讀如下:
| 方法 | 說明 |
|---|---|
| openidLogin() | 用于基于 OpenId 的驗(yàn)證 |
| headers() | 將安全標(biāo)頭添加到響應(yīng),比如說簡(jiǎn)單的 XSS 保護(hù) |
| cors() | 配置跨域資源共享( CORS ) |
| sessionManagement() | 允許配置會(huì)話管理 |
| portMapper() | 允許配置一個(gè)PortMapper(HttpSecurity#(getSharedObject(class))),其他提供SecurityConfigurer的對(duì)象使用 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() | 允許配置請(qǐng)求緩存 |
| exceptionHandling() | 允許配置錯(cuò)誤處理 |
| securityContext() | 在HttpServletRequests之間的SecurityContextHolder上設(shè)置SecurityContext的管理。 當(dāng)使用WebSecurityConfigurerAdapter時(shí),這將自動(dòng)應(yīng)用 |
| servletApi() | 將HttpServletRequest方法與在其上找到的值集成到SecurityContext中。 當(dāng)使用WebSecurityConfigurerAdapter時(shí),這將自動(dòng)應(yīng)用 |
| csrf() | 添加 CSRF 支持,使用WebSecurityConfigurerAdapter時(shí),默認(rèn)啟用 |
| logout() | 添加退出登錄支持。當(dāng)使用WebSecurityConfigurerAdapter時(shí),這將自動(dòng)應(yīng)用。默認(rèn)情況是,訪問URL”/ logout”,使HTTP Session無效來清除用戶,清除已配置的任何#rememberMe()身份驗(yàn)證,清除SecurityContextHolder,然后重定向到”/login?success” |
| anonymous() | 允許配置匿名用戶的表示方法。 當(dāng)與WebSecurityConfigurerAdapter結(jié)合使用時(shí),這將自動(dòng)應(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)的知識(shí)與內(nèi)容,后續(xù)會(huì)對(duì)HttpSecurity相關(guān)的知識(shí)進(jìn)行詳細(xì)介紹,這個(gè)也是在平時(shí)的開發(fā)中使用的最多的地方。
到此這篇關(guān)于Security中的WebSecurityConfigurerAdapter詳解的文章就介紹到這了,更多相關(guān)WebSecurityConfigurerAdapter詳解內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Java中synchronized關(guān)鍵字引出的多種鎖 問題
synchronized關(guān)鍵字是JAVA中常用的同步功能,提供了簡(jiǎn)單易用的鎖功能。這篇文章主要介紹了Java中synchronized關(guān)鍵字引出的多種鎖問題,需要的朋友可以參考下2019-07-07
SpringCloud客戶端的負(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獲取自動(dòng)化測(cè)試代碼覆蓋率
這篇文章主要介紹了如何使用pipeline和jacoco獲取自動(dòng)化測(cè)試代碼覆蓋率,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(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

