Spring Security API参考:WebSecurityConfigurerAdapter使用

Spring Security API参考:WebSecurityConfigurerAdapter使用

【免费下载链接】spring-security Spring Security 【免费下载链接】spring-security 项目地址: https://gitcode.com/gh_mirrors/spr/spring-security

1. 概述

WebSecurityConfigurerAdapter是Spring Security框架中用于配置Web安全的适配器类(Adapter Class),它实现了WebSecurityConfigurer接口,为开发者提供了一种便捷的方式来定制HTTP请求的安全规则、用户认证(Authentication)和授权(Authorization)机制。在Spring Security 5.7.0之前的版本中,这是配置Web安全的主要方式,尽管在新版本中已推荐使用组件式配置(SecurityFilterChain Bean),但了解其使用方法对于维护旧项目仍具有重要意义。

2. 核心功能与继承关系

2.1 类定义与继承结构

WebSecurityConfigurerAdapter位于org.springframework.security.config.annotation.web.configuration包下,其核心定义如下(伪代码):

public abstract class WebSecurityConfigurerAdapter 
    implements WebSecurityConfigurer<WebSecurity> {
    
    // 提供默认的安全配置实现
    protected void configure(HttpSecurity http) throws Exception {
        // 默认配置逻辑
    }
    
    // 配置用户认证信息
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        // 默认认证配置
    }
    
    // 配置WebSecurity(全局安全设置)
    public void configure(WebSecurity web) throws Exception {
        // 默认WebSecurity配置
    }
}

2.2 核心方法说明

方法签名作用调用时机
void configure(HttpSecurity http)配置HTTP请求级别的安全规则,如URL授权、表单登录、CSRF保护等每个HTTP请求处理前
void configure(AuthenticationManagerBuilder auth)配置用户认证源,如内存用户、数据库用户、LDAP用户等认证管理器初始化时
void configure(WebSecurity web)配置全局安全忽略规则,如静态资源免认证访问Spring容器启动时

3. 基本使用步骤

3.1 继承适配器类

创建自定义安全配置类,继承WebSecurityConfigurerAdapter并使用@EnableWebSecurity注解启用Web安全功能:

import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;

@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    // 重写配置方法
}

3.2 配置HTTP安全规则

通过重写configure(HttpSecurity http)方法定义URL访问权限、登录/登出行为等:

@Override
protected void configure(HttpSecurity http) throws Exception {
    http
        // 配置URL授权规则
        .authorizeRequests()
            .antMatchers("/", "/home").permitAll()  // 首页和主页允许所有用户访问
            .antMatchers("/admin/**").hasRole("ADMIN")  // /admin/**路径需要ADMIN角色
            .anyRequest().authenticated()  // 其他所有请求需要认证
            .and()
        // 配置表单登录
        .formLogin()
            .loginPage("/login")  // 自定义登录页面URL
            .defaultSuccessUrl("/dashboard", true)  // 登录成功后跳转页面
            .permitAll()  // 允许所有用户访问登录页面
            .and()
        // 配置登出
        .logout()
            .logoutUrl("/logout")  // 登出URL
            .logoutSuccessUrl("/login?logout")  // 登出成功后跳转页面
            .permitAll();
}

3.3 配置用户认证

通过重写configure(AuthenticationManagerBuilder auth)方法配置用户认证信息,支持多种数据源:

3.3.1 内存用户存储(适合开发环境)
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
    auth.inMemoryAuthentication()
        .withUser("user")
            .password("{noop}password123")  // {noop}表示不加密(仅用于演示)
            .roles("USER")
        .and()
        .withUser("admin")
            .password("{bcrypt}$2a$10$GRLdNijSQMUvl/au9ofL.eDwmoohzzS7.rmNSJZ.0FxO/BTk76klW")  // BCrypt加密密码
            .roles("ADMIN", "USER");
}
3.3.2 数据库用户存储(适合生产环境)

需配合UserDetailsService和密码编码器(PasswordEncoder)使用:

@Autowired
private UserDetailsService userDetailsService;

@Autowired
private PasswordEncoder passwordEncoder;

@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
    auth.userDetailsService(userDetailsService)
        .passwordEncoder(passwordEncoder);
}

3.4 配置全局忽略规则

通过重写configure(WebSecurity web)方法排除静态资源(如CSS、JS、图片)的安全检查:

@Override
public void configure(WebSecurity web) throws Exception {
    web.ignoring()
        .antMatchers("/css/**", "/js/**", "/images/**", "/webjars/**");
}

4. 高级配置示例

4.1 集成Spring Boot时的完整配置

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    // 注入自定义UserDetailsService
    @Autowired
    private CustomUserDetailsService userDetailsService;

    // 配置密码编码器
    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    // 配置认证管理器
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailsService)
            .passwordEncoder(passwordEncoder());
    }

    // 配置HTTP安全
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .csrf().disable()  // 开发环境可临时禁用CSRF保护(生产环境强烈建议启用)
            .authorizeRequests()
                .antMatchers("/api/public").permitAll()
                .antMatchers("/api/user").hasRole("USER")
                .antMatchers("/api/admin").hasRole("ADMIN")
                .anyRequest().authenticated()
                .and()
            .formLogin()
                .loginProcessingUrl("/login")
                .usernameParameter("username")
                .passwordParameter("password")
                .and()
            .logout()
                .logoutUrl("/logout")
                .deleteCookies("JSESSIONID");
    }
}

4.2 配置方法级安全

结合@EnableGlobalMethodSecurity注解实现方法级别的权限控制:

import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.method.configuration.GlobalMethodSecurityConfiguration;

@EnableGlobalMethodSecurity(
    prePostEnabled = true,  // 启用@PreAuthorize和@PostAuthorize注解
    securedEnabled = true,  // 启用@Secured注解
    jsr250Enabled = true    // 启用JSR-250注解(如@RolesAllowed)
)
public class MethodSecurityConfig extends GlobalMethodSecurityConfiguration {
    // 无需额外配置,注解即可生效
}

在控制器方法中使用:

import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class AdminController {

    @PreAuthorize("hasRole('ADMIN') and #id > 0")
    @GetMapping("/admin/users/{id}")
    public String getUserById(Long id) {
        return "User info for ID: " + id;
    }
}

5. 版本兼容性与迁移指南

5.1 版本变更说明

Spring Security版本WebSecurityConfigurerAdapter状态推荐配置方式
5.6.x及之前可用(默认配置方式)继承WebSecurityConfigurerAdapter
5.7.0及之后标记为@Deprecated(不推荐使用)组件式配置(SecurityFilterChain Bean)
6.0.0及之后完全移除必须使用组件式配置

5.2 从WebSecurityConfigurerAdapter迁移到SecurityFilterChain

Spring Security 5.7+推荐使用组件式配置,通过定义SecurityFilterChain Bean替代继承适配器类:

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.web.SecurityFilterChain;

@Configuration
public class SecurityConfig {

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http
            .authorizeRequests()
                .antMatchers("/public/**").permitAll()
                .anyRequest().authenticated()
                .and()
            .formLogin()
                .loginPage("/login")
                .permitAll();
        return http.build();
    }
}

6. 常见问题与解决方案

6.1 密码加密与{noop}前缀问题

问题:直接使用明文密码时抛出java.lang.IllegalArgumentException: There is no PasswordEncoder mapped for the id "null"异常。

原因:Spring Security 5+默认要求所有密码必须使用加密存储,并通过前缀指定加密算法(如{bcrypt}、{noop}等)。

解决方案

  1. 开发环境临时使用{noop}前缀允许明文密码(不推荐生产环境):
    .withUser("user").password("{noop}password").roles("USER")
    
  2. 生产环境配置密码编码器:
    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }
    

6.2 CSRF保护导致POST请求403错误

问题:启用CSRF保护时,前端表单提交POST请求返回403 Forbidden。

解决方案:在表单中添加CSRF令牌:

<form action="/login" method="post">
    <input type="hidden" th:name="${_csrf.parameterName}" th:value="${_csrf.token}" />
    <input type="text" name="username" />
    <input type="password" name="password" />
    <button type="submit">登录</button>
</form>

6.3 静态资源被拦截问题

问题:CSS、JS等静态资源无法加载,浏览器控制台报403错误。

解决方案:通过WebSecurity配置忽略静态资源:

@Override
public void configure(WebSecurity web) throws Exception {
    web.ignoring()
        .antMatchers("/css/**", "/js/**", "/images/**");
}

7. 总结

WebSecurityConfigurerAdapter作为Spring Security历史上重要的配置方式,为开发者提供了直观的安全配置体验。尽管在新版本中已被组件式配置替代,但理解其设计思想和使用方法对于掌握Spring Security的核心原理仍至关重要。在实际项目中,应根据使用的Spring Security版本选择合适的配置方式,并始终遵循安全最佳实践(如密码加密、启用CSRF保护等)。

对于新开发的项目,强烈建议直接采用Spring Security 5.7+推荐的组件式配置(SecurityFilterChain Bean),以获得更好的灵活性和未来兼容性。

【免费下载链接】spring-security Spring Security 【免费下载链接】spring-security 项目地址: https://gitcode.com/gh_mirrors/spr/spring-security

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值