Spring Security(无SpringBoot):请求未被认证/授权问题排查
问题排查:Spring Security未拦截请求&自定义过滤器不生效
问题描述
- 为深入理解Spring底层原理,在学习SpringBoot前先上手Spring框架,配置基础Security Config后,期望所有路由都需认证,但所有路径均可直接访问,未触发认证/授权校验。
- 自定义
TenantFilter并尝试加入过滤器链,doFilter()中添加了日志语句,但请求时日志未打印。 - 服务器启动时,
SecurityFilterChainBean中的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时直接返回响应内容,未触发登录校验。
问题排查与解决
请求匹配规则覆盖不全
当前配置的/*仅能匹配一级路径(如/test),无法覆盖/app/test这类多级路径。更简洁的做法是直接设置所有请求都需认证,替换原authorizeHttpRequests配置:http.authorizeHttpRequests(authz -> authz .anyRequest().authenticated() )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}; } }
- 方式一:web.xml配置
自定义过滤器生效问题
确保过滤器被Spring管理(添加@Component注解或在配置类中用@Bean声明),再取消addFilterBefore的注释:@Bean public TenantFilter tenantFilter() { return new TenantFilter(); } // 在filterChain中使用 http.addFilterBefore(tenantFilter(), AuthorizationFilter.class)
内容的提问来源于stack exchange,提问作者Mathews Mathai
相关产品推荐
相关产品推荐

