You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Boot启动报错:无法判断请求匹配模式类型(Spring Security 6)

解决Spring Boot 3 + Spring Security 6启动异常:无法判断请求匹配模式类型

运行Spring Boot应用时启动失败,抛出异常:
此方法无法判断这些模式是否为Spring MVC模式。如果该端点是Spring MVC端点,请使用requestMatchers(MvcRequestMatcher);否则,请使用requestMatchers(AntPathRequestMatcher)。

环境:Spring Boot 3 + Spring Security 6


相关代码

Spring Security配置类

package com.ronit.SpringSecurityTutorial.configuration;

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.authentication.dao.DaoAuthenticationProvider;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;

@EnableWebSecurity
@Configuration
public class SecurityConfiguration {

    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    @Bean
    AuthenticationManager authManager(UserDetailsService detailsService) {
        DaoAuthenticationProvider daoProvider = new DaoAuthenticationProvider();
        daoProvider.setUserDetailsService(detailsService);
        return new ProviderManager(daoProvider);
    }

    @SuppressWarnings("removal")
    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        return http.csrf(csrf -> csrf.disable()).authorizeHttpRequests(auth -> {
            auth.anyRequest().authenticated();
            auth.requestMatchers("/auth/**").permitAll();
            auth.anyRequest().authenticated();
        }).httpBasic().and().build();
    }
}

Spring Boot启动类

package com.ronit.SpringSecurityTutorial;

import java.util.HashSet;
import java.util.Set;

import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.security.crypto.password.PasswordEncoder;

import com.ronit.SpringSecurityTutorial.models.ApplicationUser;
import com.ronit.SpringSecurityTutorial.models.Role;
import com.ronit.SpringSecurityTutorial.repository.RoleRepository;
import com.ronit.SpringSecurityTutorial.repository.UserRepository;

@SpringBootApplication
public class SpringSecurityTutorialApplication {
    public static void main(String[] args) {
        SpringApplication.run(SpringSecurityTutorialApplication.class,args);
    }

    @Bean
    CommandLineRunner run(RoleRepository roleRepository, UserRepository userRepository,
            PasswordEncoder passwordEncoder) {
        return args -> {
            if (roleRepository.findByAuthority("ADMIN").isPresent())
                return;
            Role adminRole = roleRepository.save(new Role("ADMIN"));
            roleRepository.save(new Role("USER"));

            Set<Role> roles = new HashSet<>();
            roles.add(adminRole);
            ApplicationUser admin = new 
            ApplicationUser(1, "Admin", passwordEncoder.encode("Password"), roles);
            userRepository.save(admin);
        };
    }
}

pom.xml依赖

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-jpa</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-security</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-devtools</artifactId>
        <scope>runtime</scope>
        <optional>true</optional>
    </dependency>
    <dependency>
        <groupId>com.h2database</groupId>
        <artifactId>h2</artifactId>
        <scope>runtime</scope>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>
</dependencies>

问题原因及修复方案

核心问题

  1. 请求匹配器类型不明确:Spring Security 6对请求匹配的校验更严格,直接用字符串路径调用requestMatchers时,框架无法自动识别是Spring MVC端点还是普通路径,必须明确指定匹配器类型。
  2. 授权规则顺序错误:原配置先设置auth.anyRequest().authenticated(),后续的permitAll规则永远不会被匹配到,因为anyRequest会匹配所有请求。

修改后的Spring Security配置类

package com.ronit.SpringSecurityTutorial.configuration;

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.authentication.dao.DaoAuthenticationProvider;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.servlet.util.matcher.MvcRequestMatcher;
import org.springframework.web.servlet.handler.HandlerMappingIntrospector;

@EnableWebSecurity
@Configuration
public class SecurityConfiguration {

    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    @Bean
    AuthenticationManager authManager(UserDetailsService detailsService) {
        DaoAuthenticationProvider daoProvider = new DaoAuthenticationProvider();
        daoProvider.setUserDetailsService(detailsService);
        daoProvider.setPasswordEncoder(passwordEncoder()); // 补充密码编码器,避免后续认证失败
        return new ProviderManager(daoProvider);
    }

    @Bean
    MvcRequestMatcher.Builder mvc(HandlerMappingIntrospector introspector) {
        return new MvcRequestMatcher.Builder(introspector);
    }

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http, MvcRequestMatcher.Builder mvc) throws Exception {
        return http.csrf(csrf -> csrf.disable())
                .authorizeHttpRequests(auth -> {
                    // 先配置无需认证的路径
                    auth.requestMatchers(mvc.pattern("/auth/**")).permitAll();
                    // 其余所有请求需要认证
                    auth.anyRequest().authenticated();
                })
                .httpBasic()
                .and()
                .build();
    }
}

修改说明

  1. 明确指定MvcRequestMatcher:注入HandlerMappingIntrospector并创建MvcRequestMatcher.Builder,告诉框架使用Spring MVC的请求匹配规则,解决模式类型无法判断的问题。
  2. 调整授权规则顺序:先设置permitAll的路径,再配置anyRequest().authenticated(),确保规则按从上到下的顺序匹配。
  3. 补充密码编码器设置:原DaoAuthenticationProvider未绑定密码编码器,会导致用户登录时认证失败,这里补上该配置。

额外说明

  • 启动类和pom.xml无需修改,保持原代码即可。
  • 若需使用非Spring MVC的路径匹配(如静态资源),可替换为AntPathRequestMatcher,示例:requestMatchers(new AntPathRequestMatcher("/auth/**")).permitAll(),但Spring MVC接口优先使用MvcRequestMatcher。

内容的提问来源于stack exchange,提问作者Ronit Pandey

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.14 12:31:07