Spring Security 6 自定义登录页完整配置指南

本文详解 spring security 6 中如何替代已废弃的 `websecurityconfigureradapter`,通过 `securityfilterchain` 配置自定义登录页、表单认证与用户管理,并解决常见 `mvcrequestmatcher` 初始化异常。

Spring Security 6 彻底移除了 WebSecurityConfigurerAdapter,转而采用基于函数式 Bean 声明的安全配置模型。要成功启用自定义登录页(如 /login),关键在于正确构建 SecurityFilterChain Bean,同时确保 Spring MVC 与 Spring Security 共享同一应用上下文——这是解决你遇到的 No bean named 'mvcHandlerMappingIntrospector' 异常的核心前提。

✅ 正确配置 SecurityFilterChain

你的 filterChain 方法逻辑基本正确,但存在两个关键问题:

  1. requestMatchers() 的匹配器类型不兼容:Spring Security 6 默认使用 MvcRequestMatcher(依赖 Spring MVC 的 HandlerMappingIntrospector),而你未显式启用 MVC 支持或切换为更轻量的 AntPathRequestMatcher;
  2. 缺少 CSRF 配置(Spring Security 6 默认启用):若登录表单未携带 _csrf token,将导致 403 拒绝;

以下是修复后的完整 SecurityConfiguration:

package main.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.Customizer;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.factory.PasswordEncoderFactories;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher; // ✅ 显式使用 AntPathRequestMatcher

@Configuration
@EnableWebSecurity
public class SecurityConfiguration {

    @Bean
    public PasswordEncoder passwordEncoder() {
        return PasswordEncoderFactories.createDelegatingPasswordEncoder();
    }

    @Bean
    public UserDetailsService users() {
        UserDetails admin = User.withUsername("admin")
                .password(passwordEncoder().encode("admin"))
                .roles("ADMIN", "EMPLOYEE")
                .build();
        UserDetails employee = User.withUsername("employee")
                .password(passwordEncoder().encode("employee"))
                .roles("EMPLOYEE")
                .build();
        UserDetails client = User.withUsername("client")
                .password(passwordEncoder().encode("client"))
                .roles("CLIENT")
                .build();
        return new InMemoryUserDetailsManager(admin, employee, client);
    }

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http
            .authorizeHttpRequests(authz -> authz
                .requestMatchers(new AntPathRequestMatcher("/"), new AntPathRequestMatcher("/login")).permitAll() // ✅ 使用 AntPathRequestMatcher
                .anyRequest().authenticated()
            )
            .formLogin(form -> form
                .loginPage("/login")                     // 自定义登录页路径
                .loginProcessingUrl("/checkUserAccount") // 表单 POST 目标
                .defaultSuccessUrl("/", true)            // 登录成功后重定向(true=强制跳转)
                .permitAll()
            )
            .logout(logout -> logout
                .logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
                .logoutSuccessUrl("/")
                .invalidateHttpSession(true)
                .permitAll()
            )
            .csrf(csrf -> csrf.disable()); // ⚠️ 开发阶段可禁用(生产环境务必启用并配合 Thymeleaf 的 csrf:token)

        return http.build();
    }
}

? 关键修复说明

问题 解决方案 原因
mvcHandlerMappingIntrospector 缺失异常 替换 requestMatchers("/") 为 requestMatchers(new AntPathRequestMatcher("/")) 避免触发 MvcRequestMatcher,消除对 Spring MVC 内部 Bean 的强依赖
登录提交 403 错误 显式调用 .csrf(csrf -> csrf.disable())(开发期) Spring Security 6 默认启用 CSRF 保护,需在表单中添加 (Thymeleaf)或禁用(仅限测试)
SecurityInitializer 冗余 彻底删除该类 Spring Boot 2.7+ + @EnableWebSecurity 已自动注册安全过滤器链,AbstractSecurityWebApplicationInitializer 已过时且与新模型冲突

? 登录页面适配(Thymeleaf)

确保你的 login.html 表单包含 CSRF token(生产环境必需):

同时,在 pom.xml 中确认已引入 Spring Security Thymeleaf 集成:


    org.thymeleaf.extras
    thymeleaf-extras-springsecurity6

✅ 最终验证步骤

  1. 删除 SecurityInitializer.java;
  2. 确保 spring-webmvc 和 spring-security-web 版本与 Spring Boot 兼容(推荐直接使用 Spring Boot Starter);
  3. 启动应用,访问 http://localhost:8080/login —— 应正常渲染自定义页面;
  4. 提交表单,验证能否成功登录并跳转至 /。
? 提示:生产环境切勿禁用 CSRF!应保留 .csrf(csrf -> csrf.enable()) 并在 Thymeleaf 模板中正确注入 token。如使用非 Thymeleaf 视图(如 JSP/FreeMarker),需按对应模板引擎文档注入 _csrf 参数。

通过以上配置,你已完整迁移至 Spring Security 6 的现代安全模型,既支持自定义登录页,又保持了配置的清晰性与可维护性。