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

Spring Security(无SpringBoot):请求未被认证/授权问题排查

问题排查:Spring Security未拦截请求&自定义过滤器不生效

问题描述

  • 为深入理解Spring底层原理,在学习SpringBoot前先上手Spring框架,配置基础Security Config后,期望所有路由都需认证,但所有路径均可直接访问,未触发认证/授权校验。
  • 自定义TenantFilter并尝试加入过滤器链,doFilter()中添加了日志语句,但请求时日志未打印。
  • 服务器启动时,SecurityFilterChain Bean中的SECURING IT日志正常输出,说明该Bean已成功注册。

环境信息

依赖版本:

  • spring-context 6.1.2
  • spring-webmvc 6.1.2
  • spring-security-config 6.1.2
  • jakarta.servlet-api 6.1.0-M1
  • spring-security-web 6.1.2
    容器:Tomcat 11

配置代码

@Configuration
@EnableWebMvc
@EnableWebSecurity(debug = true)
//@EnableWebMvcSecurity
@ComponentScan(basePackages = "org.example")
public class WebConfig implements WebMvcConfigurer {
    @Override
    public void addViewControllers(ViewControllerRegistry registry) {
        registry.addViewController("/tryJsp").setViewName("index");
    }


    @Bean
    public UserDetailsService userDetailsService() {
        UserDetails userDetails = User.builder().username("user")
                .password(passwordEncoder().encode("password"))
                .roles("USER")
                .build();

        return new InMemoryUserDetailsManager(userDetails);
    }

    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }
    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        System.out.println("SECURING IT");

        http.authorizeHttpRequests((authz) -> authz
                .requestMatchers(antMatcher("/app/*")).authenticated()
                        .requestMatchers(antMatcher("/app/test")).authenticated()
                        .requestMatchers(antMatcher("/*")).authenticated()
                        .requestMatchers(antMatcher("*/*")).authenticated()
        )
                //.addFilterBefore(new TenantFilter(), AuthorizationFilter.class)
                .httpBasic(Customizer.withDefaults())
                .formLogin(Customizer.withDefaults());
        return http.build();
    }
}

控制器代码

@GetMapping("/test")
@ResponseBody
public ResponseEntity<String> getRoute(HttpServletRequest request) {
    String requestURL = request.getRequestURL().toString();
    System.out.println("Request URL: " + requestURL); //prints http://localhost:8080/app/test
    String requestURI = request.getRequestURI();
    System.out.println("Request URI: " + requestURI); //prints  /app/test
    return ResponseEntity.ok("Yet another plain string response");
}

预期与实际结果

  • 预期:Spring Security拦截请求,显示默认登录表单。
  • 实际:访问路由/app/test时直接返回响应内容,未触发登录校验。

问题排查与解决

  1. 请求匹配规则覆盖不全
    当前配置的/*仅能匹配一级路径(如/test),无法覆盖/app/test这类多级路径。更简洁的做法是直接设置所有请求都需认证,替换原authorizeHttpRequests配置:

    http.authorizeHttpRequests(authz -> authz
        .anyRequest().authenticated()
    )
    
  2. Spring Security过滤器链未接入Servlet容器
    纯Spring MVC(非SpringBoot)环境下,需手动注册DelegatingFilterProxy到Servlet容器,否则过滤器链不会生效,可通过两种方式实现:

    • 方式一:web.xml配置
      <filter>
          <filter-name>springSecurityFilterChain</filter-name>
          <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
      </filter>
      <filter-mapping>
          <filter-name>springSecurityFilterChain</filter-name>
          <url-pattern>/*</url-pattern>
      </filter-mapping>
      
    • 方式二:Java配置ServletInitializer
      创建类继承AbstractAnnotationConfigDispatcherServletInitializer,重写getServletFilters()方法:
      public class AppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
          @Override
          protected Class<?>[] getRootConfigClasses() {
              return new Class[]{WebConfig.class};
          }
      
          @Override
          protected Class<?>[] getServletConfigClasses() {
              return null;
          }
      
          @Override
          protected String[] getServletMappings() {
              return new String[]{"/"};
          }
      
          @Override
          protected Filter[] getServletFilters() {
              DelegatingFilterProxy securityFilter = new DelegatingFilterProxy("springSecurityFilterChain");
              return new Filter[]{securityFilter};
          }
      }
      
  3. 自定义过滤器生效问题
    确保过滤器被Spring管理(添加@Component注解或在配置类中用@Bean声明),再取消addFilterBefore的注释:

    @Bean
    public TenantFilter tenantFilter() {
        return new TenantFilter();
    }
    
    // 在filterChain中使用
    http.addFilterBefore(tenantFilter(), AuthorizationFilter.class)
    

内容的提问来源于stack exchange,提问作者Mathews Mathai

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.03 07:00:25