
WebSecurityConfigurerAdapter
是 Spring Security 中的一个适配器类,专门用于帮助开发者配置 Web 应用的安全设置。它是一个方便的抽象类,允许我们通过继承它并重写其方法,来定制应用的安全行为,比如配置认证和授权规则、处理用户会话管理、跨站请求伪造 (CSRF) 防护等。
在 Spring Security 5.7 版本后,WebSecurityConfigurerAdapter
已被标记为过时,推荐使用新的配置方式。
使用 WebSecurityConfigurerAdapter
开发者可以通过继承 WebSecurityConfigurerAdapter
并重写其配置方法来自定义安全策略:
- 重写
configure(HttpSecurity http)
方法:用于配置请求的授权规则和安全过滤器链。 - 重写
configure(AuthenticationManagerBuilder auth)
方法:用于配置认证方式,比如基于内存的用户、数据库认证、LDAP 认证等。
示例
以下是一个 WebSecurityConfigurerAdapter
的简单示例:
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/public/**").permitAll() // 允许公开访问的路径
.anyRequest().authenticated() // 其他请求需要认证
.and()
.formLogin() // 启用表单登录
.loginPage("/login") // 自定义登录页面
.permitAll()
.and()
.logout() // 启用注销
.permitAll();
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication()
.withUser("user").password("{noop}password").roles("USER")
.and()
.withUser("admin").password("{noop}admin").roles("ADMIN");
}
}
Spring Security 5.7 之后的推荐替代方法
在 Spring Security 5.7 及之后,WebSecurityConfigurerAdapter
被弃用,推荐使用 SecurityFilterChain
和 AuthenticationManager
的配置方式:
@Configuration
public class SecurityConfig {
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/public/**").permitAll()
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login")
.permitAll()
.and()
.logout()
.permitAll();
return http.build();
}
@Bean
public InMemoryUserDetailsManager userDetailsService() {
UserDetails user = User.withDefaultPasswordEncoder()
.username("user")
.password("password")
.roles("USER")
.build();
UserDetails admin = User.withDefaultPasswordEncoder()
.username("admin")
.password("admin")
.roles("ADMIN")
.build();
return new InMemoryUserDetailsManager(user, admin);
}
}
总结
WebSecurityConfigurerAdapter
是用于配置 Spring Security 的一个便利适配器类,虽然已在新版本中被替代,但它在旧版本中是主要的安全配置方式。通过新方法,开发者可以更灵活、模块化地管理 Web 应用的安全配置。
是的,你在 WebSecurityConfig
类中配置了 Spring Security,确保 MyAuthenticationProvider
和 PhoneAuthenticationProvider
被正确注册为认证提供者,并且自定义的认证过滤器也被添加到了过滤器链中。下面是对你的配置文件的详细解释:
WebSecurityConfig.java
package com.productQualification.api.config;
import com.productQualification.api.filter.PhoneNumAuthenticationFilter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.ProviderManager;
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.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.web.cors.CorsConfiguration;
import java.util.Arrays;
/**
* @author William Guo
*/
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private MyAuthenticationProvider myAuthenticationProvider;
@Autowired
private MyAuthenticationFailHandler myAuthenticationFailHandler;
@Autowired
private MyAuthenticationSuccessHandler myAuthenticationSuccessHandler;
@Autowired
private PhoneAuthenticationProvider phoneAuthenticationProvider;
@Value("${spring.profiles}")
private String profiles;
@Bean
public PhoneNumAuthenticationFilter phoneNumAuthenticationFilter() throws Exception {
PhoneNumAuthenticationFilter filter = new PhoneNumAuthenticationFilter();
filter.setAuthenticationManager(authenticationManagerBean()); // 设置认证管理器
filter.setAuthenticationSuccessHandler(myAuthenticationSuccessHandler); // 设置登录成功处理器
filter.setAuthenticationFailureHandler(myAuthenticationFailHandler); // 设置登录失败处理器
filter.setFilterProcessesUrl("/admin/signInByPhone"); // 设置处理的URL
return filter;
}
@Bean
public UsernamePasswordAuthenticationFilter myUsernamePasswordAuthenticationFilter() throws Exception {
UsernamePasswordAuthenticationFilter filter = new UsernamePasswordAuthenticationFilter();
filter.setAuthenticationManager(authenticationManagerBean()); // 设置认证管理器
filter.setAuthenticationSuccessHandler(myAuthenticationSuccessHandler); // 设置登录成功处理器
filter.setAuthenticationFailureHandler(myAuthenticationFailHandler); // 设置登录失败处理器
filter.setFilterProcessesUrl("/admin/signIn"); // 设置处理的URL
return filter;
}
@Override
protected void configure(HttpSecurity http) throws Exception {
// 关闭csrf
http.csrf().disable();
// 开启cors跨域支持
http.cors().configurationSource(request -> {
CorsConfiguration corsConfiguration = new CorsConfiguration().applyPermitDefaultValues();
corsConfiguration.addAllowedMethod(CorsConfiguration.ALL); // 允许所有方法
corsConfiguration.setAllowCredentials(true); // 允许携带cookie
if ("prod".equals(profiles)) {
corsConfiguration.addAllowedOrigin("https://www.crossbiog.com");
corsConfiguration.addAllowedOrigin("http://www.crossbiog.com");
corsConfiguration.addAllowedOrigin("https://crossbiog.com");
corsConfiguration.addAllowedOrigin("http://crossbiog.com");
corsConfiguration.addAllowedOrigin("https://kxlist.cn");
corsConfiguration.addAllowedOrigin("https://www.kxlist.cn");
}
return corsConfiguration;
});
http.authorizeRequests()
.anyRequest().permitAll() // 允许所有请求
// .and().formLogin().loginPage("/admin/signIn").defaultSuccessUrl("/admin/signInSuccess")
// .failureHandler(myAuthenticationFailHandler)
// .antMatchers(HttpMethod.GET, "/admin/signIn")
// .permitAll()
// .antMatchers(HttpMethod.POST, "/admin")
// .permitAll()
// // swagger
// .antMatchers(HttpMethod.GET, "/v2/api-docs", "/swagger-resources/**", "/webjars/**", "/swagger-ui.html")
// .permitAll()
// .anyRequest()
// .authenticated()
// .and()
// .sessionManagement()
// .and()
// .httpBasic();
;
// 把账户密码验证过滤器加到拦截器链中
http.addFilterAt(myUsernamePasswordAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class)
.authenticationProvider(myAuthenticationProvider); // 注册账户密码验证提供者
// 把手机号认证过滤器加到拦截器链中
http.addFilterAfter(phoneNumAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class)
.authenticationProvider(phoneAuthenticationProvider); // 注册手机号验证提供者
}
@Override
protected AuthenticationManager authenticationManager() {
ProviderManager authenticationManager = new ProviderManager(Arrays.asList(phoneAuthenticationProvider));
// 不擦除认证密码,擦除会导致TokenBasedRememberMeServices因为找不到Credentials再调用UserDetailsService而抛出UsernameNotFoundException
authenticationManager.setEraseCredentialsAfterAuthentication(false);
return authenticationManager;
}
}
解释
-
注解:
@Configuration
:标记该类为配置类。@EnableWebSecurity
:启用 Spring Security 的 Web 安全支持。@EnableGlobalMethodSecurity(prePostEnabled = true)
:启用全局方法安全,支持@PreAuthorize
和@PostAuthorize
注解。
-
注入依赖:
@Autowired
:注入MyAuthenticationProvider
、MyAuthenticationFailHandler
、MyAuthenticationSuccessHandler
和PhoneAuthenticationProvider
。
-
配置 CORS:
http.cors().configurationSource(...)
:配置 CORS 支持,允许特定的域名访问。
-
关闭 CSRF:
http.csrf().disable()
:关闭 CSRF 保护,适用于不需要 CSRF 保护的场景。
-
配置 HTTP 安全:
http.authorizeRequests().anyRequest().permitAll()
:允许所有请求,可以根据需要进行更细粒度的权限控制。http.addFilterAt(...)
:将UsernamePasswordAuthenticationFilter
添加到过滤器链中,并注册MyAuthenticationProvider
。http.addFilterAfter(...)
:将PhoneNumAuthenticationFilter
添加到过滤器链中,并注册PhoneAuthenticationProvider
。
-
配置认证管理器:
authenticationManager()
:重写authenticationManager
方法,创建一个ProviderManager
并注册PhoneAuthenticationProvider
。设置setEraseCredentialsAfterAuthentication(false)
以防止擦除认证密码。
总结
通过上述配置,Spring Security 会在用户尝试登录时调用 MyAuthenticationProvider
或 PhoneAuthenticationProvider
进行认证。确保你的 WebSecurityConfig
类正确配置了认证提供者和自定义的认证过滤器,这样在用户登录时,程序一定会经过这些类。
希望这些解释能帮助你更好地理解和配置 Spring Security。