Spring Security结合JWT时Ant Matcher未按指定角色限制端点权限的问题排查
问题分析与解决方案
首先,你的问题核心在于Spring Security的antMatchers使用了正则表达式路径,但antMatchers实际上是基于Ant风格路径模式匹配的,而非正则表达式。这导致你配置的角色权限规则根本没有匹配到对应的请求路径,所有已认证用户都会通过anyRequest().authenticated()的规则被允许访问,完全绕过了你设置的角色权限校验。
具体修正步骤
1. 修正路径匹配规则
你有两种可选的修正方式:
方式一:改用Ant风格路径匹配
把配置中的正则路径替换为Ant风格路径,这是antMatchers的标准用法:
@Override protected void configure(HttpSecurity http) throws Exception { http.authorizeRequests() .antMatchers("/login", "/users/**").permitAll() // 使用Ant风格的*匹配单个ID路径段 .antMatchers(PUT, "/answers/*").hasAnyAuthority("ROLE_INSTRUCTOR") .antMatchers(GET, "/answers/*/is-correct").hasAnyAuthority("ROLE_STUDENT") .anyRequest().authenticated() .and() .addFilter(new CustomAuthenticationFilter(authenticationManagerBean())) .addFilterBefore(new CustomAuthorizationFilter(), UsernamePasswordAuthenticationFilter.class) .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS) .and() .csrf().disable(); }
方式二:改用regexMatchers适配正则路径
如果你需要精确匹配数字ID的路径,可以使用regexMatchers替代antMatchers,保留你的正则表达式:
@Override protected void configure(HttpSecurity http) throws Exception { http.authorizeRequests() .antMatchers("/login", "/users/**").permitAll() // 使用regexMatchers支持正则表达式路径 .regexMatchers(PUT, "/answers/(\\d+)").hasAnyAuthority("ROLE_INSTRUCTOR") .regexMatchers(GET, "/answers/(\\d+)/is-correct").hasAnyAuthority("ROLE_STUDENT") .anyRequest().authenticated() .and() .addFilter(new CustomAuthenticationFilter(authenticationManagerBean())) .addFilterBefore(new CustomAuthorizationFilter(), UsernamePasswordAuthenticationFilter.class) .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS) .and() .csrf().disable(); }
2. 可选:简化权限配置写法
如果你的角色都是以ROLE_前缀开头,可以使用hasRole替代hasAnyAuthority,这样不用写完整的ROLE_XXX字符串:
.antMatchers(PUT, "/answers/*").hasRole("INSTRUCTOR") .antMatchers(GET, "/answers/*/is-correct").hasRole("STUDENT")
(hasRole会自动在角色名前添加ROLE_前缀,所以这里只需要写INSTRUCTOR而非ROLE_INSTRUCTOR)
3. 验证权限注入正确性
你的CustomAuthorizationFilter中权限注入逻辑是正确的,但可以加一行日志确认权限是否正确加载:
// 在CustomAuthorizationFilter的权限处理代码中添加 log.info("User {} is granted with authorities: {}", username, authorities);
为什么原配置不生效?
Spring Security的antMatchers遵循Ant路径语法规则:
*匹配任意非路径分隔符的字符**匹配任意字符(包括路径分隔符/)?匹配单个字符
你写的/answers/(\\d+)是正则表达式格式,antMatchers无法识别这种语法,导致对应的权限规则从未被触发,所有已认证用户都落入了anyRequest().authenticated()的规则范围,自然会出现角色越权访问的情况。
内容的提问来源于stack exchange,提问作者Dolphy the Reaper
相关产品推荐
相关产品推荐

