Security中的WebSecurityConfigurerAdapter詳解
本文來(lái)詳細(xì)說(shuō)下security中的WebSecurityConfigurerAdapter
概述
今天我們要進(jìn)一步的的學(xué)習(xí)如何自定義配置 Spring Security 我們已經(jīng)多次提到了 WebSecurityConfigurerAdapter ,而且我們知道 Spring Boot 中的自動(dòng)配置實(shí)際上是通過(guò)自動(dòng)配置包下的 SecurityAutoConfiguration 總配置類(lèi)上導(dǎo)入的 Spring Boot Web 安全配置類(lèi) SpringBootWebSecurityConfiguration 來(lái)配置的。
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類(lèi)圖

常用配置
下面貼一下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 {
/**
* 自定義用戶(hù)認(rèn)證邏輯
*/
@Autowired
private UserDetailsService userDetailsService;
/**
* 認(rèn)證失敗處理類(lèi)
*/
@Autowired
private AuthenticationEntryPointImpl unauthorizedHandler;
/**
* 退出處理類(lèi)
*/
@Autowired
private LogoutSuccessHandlerImpl logoutSuccessHandler;
/**
* token認(rèn)證過(guò)濾器
*/
@Autowired
private JwtAuthenticationTokenFilter authenticationTokenFilter;
/**
* 跨域過(guò)濾器
*/
@Autowired
private CorsFilter corsFilter;
/**
* 解決 無(wú)法直接注入 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ù)庫(kù)和security
auth.userDetailsService(userDetailsService).passwordEncoder(bCryptPasswordEncoder());
}
/**
* anyRequest | 匹配所有請(qǐng)求路徑
* access | SpringEl表達(dá)式結(jié)果為true時(shí)可以訪問(wèn)
* anonymous | 匿名可以訪問(wèn)
* denyAll | 用戶(hù)不能訪問(wèn)
* fullyAuthenticated | 用戶(hù)完全認(rèn)證可以訪問(wèn)(非remember-me下自動(dòng)登錄)
* hasAnyAuthority | 如果有參數(shù),參數(shù)表示權(quán)限,則其中任何一個(gè)權(quán)限可以訪問(wèn)
* hasAnyRole | 如果有參數(shù),參數(shù)表示角色,則其中任何一個(gè)角色可以訪問(wèn)
* hasAuthority | 如果有參數(shù),參數(shù)表示權(quán)限,則其權(quán)限可以訪問(wèn)
* hasIpAddress | 如果有參數(shù),參數(shù)表示IP地址,如果用戶(hù)IP和參數(shù)匹配,則可以訪問(wèn)
* hasRole | 如果有參數(shù),參數(shù)表示角色,則其角色可以訪問(wèn)
* permitAll | 用戶(hù)可以任意訪問(wèn)
* rememberMe | 允許通過(guò)remember-me登錄的用戶(hù)訪問(wèn)
* authenticated | 用戶(hù)登錄后可訪問(wèn)
*/
@Override
protected void configure(HttpSecurity httpSecurity) throws Exception {
httpSecurity
// CSRF禁用,因?yàn)椴皇褂胹ession
.csrf().disable()
// 認(rèn)證失敗處理類(lèi)
.exceptionHandling().authenticationEntryPoint(unauthorizedHandler).and()
// 基于token,所以不需要session
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
// 過(guò)濾請(qǐng)求
.authorizeRequests()
// 對(duì)于登錄login 驗(yàn)證碼captchaImage 允許匿名訪問(wèn)
.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);
}
/***
* 核心過(guò)濾器配置方法
* @param web
* @throws Exception
*/
@Override
public void configure(WebSecurity web) throws Exception {
super.configure(web);
}
}相信已經(jīng)有人注意到了上面 WebSecurityConfigurerAdapter 中我覆寫(xiě)(@Override)了三個(gè)configure方法,我們一般會(huì)通過(guò)自定義配置這三個(gè)方法來(lái)自定義我們的安全訪問(wèn)策略。
認(rèn)證管理器配置方法
AuthenticationManagerBuilder(身份驗(yàn)證管理生成器)
void configure(AuthenticationManagerBuilder auth) 用來(lái)配置認(rèn)證管理器AuthenticationManager。說(shuō)白了就是所有 UserDetails 相關(guān)的它都管,包含 PasswordEncoder 密碼等。如果你不清楚可以通過(guò) Spring Security 中的 UserDetail 進(jìn)行了解。本文對(duì) AuthenticationManager 不做具體分析講解,后面會(huì)有專(zhuān)門(mén)的文章來(lái)講這個(gè)東西 。
常見(jiàn)用法
/**
* 身份認(rèn)證接口
*/
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService).passwordEncoder(bCryptPasswordEncoder());
}核心過(guò)濾器配置方法
WebSecurity(WEB安全)
void configure(WebSecurity web) 用來(lái)配置 WebSecurity 。而 WebSecurity 是基于 Servlet Filter 用來(lái)配置 springSecurityFilterChain 。而 springSecurityFilterChain 又被委托給了 Spring Security 核心過(guò)濾器 Bean DelegatingFilterProxy 。 相關(guān)邏輯你可以在 WebSecurityConfiguration 中找到。我們一般不會(huì)過(guò)多來(lái)自定義 WebSecurity , 使用較多的使其ignoring() 方法用來(lái)忽略 Spring Security 對(duì)靜態(tài)資源的控制。
安全過(guò)濾器鏈配置方法
HttpSecurity(HTTP請(qǐng)求安全處理)
void configure(HttpSecurity http) 這個(gè)是我們使用最多的,用來(lái)配置 HttpSecurity 。 HttpSecurity 用于構(gòu)建一個(gè)安全過(guò)濾器鏈 SecurityFilterChain 。SecurityFilterChain 最終被注入核心過(guò)濾器 。 HttpSecurity 有許多我們需要的配置。我們可以通過(guò)它來(lái)進(jìn)行自定義安全訪問(wèn)策略。所以我們單獨(dú)開(kāi)一章來(lái)講解這個(gè)東西。
HttpSecurity 配置
HttpSecurity 是后面幾篇文章的重點(diǎn),我們將實(shí)際操作它來(lái)實(shí)現(xiàn)一些實(shí)用功能。所以本文要著重介紹它。
HttpSecurity 類(lèi)圖

默認(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)配置。通過(guò)以上的配置,你的應(yīng)用具備了一下的功能:
- 所有的請(qǐng)求訪問(wèn)都需要被授權(quán)。
- 使用 form 表單進(jìn)行登陸(默認(rèn)路徑為/login),也就是前幾篇我們見(jiàn)到的登錄頁(yè)。
- 防止 CSRF 攻擊、 XSS 攻擊。
- 啟用 HTTP Basic 認(rèn)證
常用方法解讀
HttpSecurity 使用了builder 的構(gòu)建方式來(lái)靈活制定訪問(wèn)策略。最早基于 XML 標(biāo)簽對(duì) HttpSecurity 進(jìn)行配置?,F(xiàn)在大部分使用 javaConfig方式。常用的方法解讀如下:
| 方法 | 說(shuō)明 |
|---|---|
| openidLogin() | 用于基于 OpenId 的驗(yàn)證 |
| headers() | 將安全標(biāo)頭添加到響應(yīng),比如說(shuō)簡(jiǎn)單的 XSS 保護(hù) |
| cors() | 配置跨域資源共享( CORS ) |
| sessionManagement() | 允許配置會(huì)話(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限制訪問(wèn) |
| 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)情況是,訪問(wèn)URL”/ logout”,使HTTP Session無(wú)效來(lái)清除用戶(hù),清除已配置的任何#rememberMe()身份驗(yàn)證,清除SecurityContextHolder,然后重定向到”/login?success” |
| anonymous() | 允許配置匿名用戶(hù)的表示方法。 當(dāng)與WebSecurityConfigurerAdapter結(jié)合使用時(shí),這將自動(dòng)應(yīng)用。 默認(rèn)情況下,匿名用戶(hù)將使用org.springframework.security.authentication.AnonymousAuthenticationToken表示,并包含角色 “ROLE_ANONYMOUS” |
| formLogin() | 指定支持基于表單的身份驗(yàn)證。如果未指定FormLoginConfigurer#loginPage(String),則將生成默認(rèn)登錄頁(yè)面 |
| oauth2Login() | 根據(jù)外部OAuth 2.0或OpenID Connect 1.0提供程序配置身份驗(yàn)證 |
| requiresChannel() | 配置通道安全。為了使該配置有用,必須提供至少一個(gè)到所需信道的映射 |
| httpBasic() | 配置 Http Basic 驗(yàn)證 |
| addFilterBefore() | 在指定的Filter類(lèi)之前添加過(guò)濾器 |
| addFilterAt() | 在指定的Filter類(lèi)的位置添加過(guò)濾器 |
| addFilterAfter() | 在指定的Filter類(lèi)的之后添加過(guò)濾器 |
| and() | 連接以上策略的連接器,用來(lái)組合安全策略。實(shí)際上就是"而且"的意思 |
本文小結(jié)
本文詳細(xì)介紹了WebSecurityConfigurerAdapter相關(guān)的知識(shí)與內(nèi)容,后續(xù)會(huì)對(duì)HttpSecurity相關(guān)的知識(shí)進(jìn)行詳細(xì)介紹,這個(gè)也是在平時(shí)的開(kāi)發(fā)中使用的最多的地方。
到此這篇關(guān)于Security中的WebSecurityConfigurerAdapter詳解的文章就介紹到這了,更多相關(guān)WebSecurityConfigurerAdapter詳解內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Java中synchronized關(guān)鍵字引出的多種鎖 問(wèn)題
synchronized關(guān)鍵字是JAVA中常用的同步功能,提供了簡(jiǎn)單易用的鎖功能。這篇文章主要介紹了Java中synchronized關(guān)鍵字引出的多種鎖問(wèn)題,需要的朋友可以參考下2019-07-07
SpringCloud客戶(hù)端的負(fù)載均衡Ribbon的實(shí)現(xiàn)
微服務(wù)架構(gòu),不可避免的存在單個(gè)微服務(wù)有多個(gè)實(shí)例,這篇文章主要介紹了SpringCloud客戶(hù)端的負(fù)載均衡Ribbon的實(shí)現(xiàn),小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2018-06-06
如何使用pipeline和jacoco獲取自動(dòng)化測(cè)試代碼覆蓋率
這篇文章主要介紹了如何使用pipeline和jacoco獲取自動(dòng)化測(cè)試代碼覆蓋率,文中通過(guò)示例代碼介紹的非常詳細(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

