如何在Spring Boot中调整OAuth2过滤级别并指定路径权限?
问题分析与解决方案
你遇到的核心问题是自定义的WebSecurityConfigurerAdapter覆盖了Spring Security OAuth2默认的资源服务器配置,导致需要OAuth2保护的路径无法正确验证令牌。当你注释掉这个Bean时,默认的OAuth2配置生效,所以接口能正常工作。
为什么会出现这个问题?
Spring Security中,WebSecurityConfigurerAdapter和ResourceServerConfigurerAdapter的配置存在优先级关系:
ResourceServerConfigurerAdapter的默认Order是3,负责处理OAuth2资源服务器的认证逻辑(比如令牌验证)。WebSecurityConfigurerAdapter的默认Order是100,负责通用的Web安全配置。
当你在自定义的WebSecurityConfigurerAdapter中使用authorizeRequests().anyRequest().hasRole("USER")时,这个配置会覆盖ResourceServer的规则,导致OAuth2的令牌过滤器没有被应用到你的API路径上,所以即使你携带了正确的令牌,请求也会被判定为无效。
正确的配置方式
我们需要把公共路径忽略和OAuth2资源保护分开配置:
1. 配置WebSecurity忽略无需过滤的路径
使用WebSecurity.ignoring()让这些路径完全跳过Spring Security的过滤器链,既高效又不会干扰OAuth2的配置:
@Configuration public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter { @Autowired UserMapper userMapper; @Bean PasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(); } @Bean UserDetailsService userDetailsService() { return username -> { User myU = userMapper.getUser(username); if (myU == null) { throw new UsernameNotFoundException("Could not find the user '" + username + "'"); } return org.springframework.security.core.userdetails.User .withUsername(myU.name) .password(myU.password) .authorities("USER", "write") .build(); }; } // 忽略公共路径,完全不经过Spring Security过滤器 @Override public void configure(WebSecurity web) throws Exception { web.ignoring() .antMatchers("/robots.txt", "/error", "/login", "/doLogout", "/home", "/pageNotFound", "/errorNonSamsung", "/snsandroidgear", "/snstheme", "/errorDesktop", "/*", "/getUrls", "/css/**", "/js/**", "/fonts/**", "/img/**", "/dologin", "/form", "/addImage", "/addThemeImage", "/exportUniqueToexcel", "/exporttoexcel", "/delete", "/activateDeactivate"); } // 配置通用Web安全(比如表单登录等,不要覆盖OAuth2规则) @Override protected void configure(HttpSecurity http) throws Exception { http .authorizeRequests() .anyRequest().authenticated() .and() .httpBasic().disable(); } }
2. 单独配置ResourceServer保护API路径
创建ResourceServerConfigurerAdapter专门处理需要OAuth2验证的路径,确保令牌逻辑生效:
@Configuration @EnableResourceServer public class ResourceServerConfiguration extends ResourceServerConfigurerAdapter { @Override public void configure(HttpSecurity http) throws Exception { http // 指定需要OAuth2保护的路径 .requestMatchers() .antMatchers("/isTagAvailable") .and() // 配置权限要求 .authorizeRequests() .anyRequest().hasAuthority("USER"); // 注意这里用hasAuthority,因为你配置的是authorities("USER", "write") } }
验证效果
配置完成后,重新测试:
- 公共路径(如
/robots.txt)可以直接访问:$ curl http://localhost:8080/robots.txt User-agent: * Disallow: / - 获取令牌正常:
$ curl -u xxxxxxx:xxxxxxx http://localhost:8080/oauth/token -d grant_type=password -d username=xxxxx -d password=xxxx -d client_id=xxxxxxx -d client_secret=xxxxxxx -d scope=write {"access_token":"f90b4bdf-a380-40d6-a6a7-5be28bd3ce99","token_type":"bearer","refresh_token":"cf507647-9f74-4ed7-a23e-92acac9ec257","expires_in":43199,"scope":"write"} - 携带令牌访问受保护的接口:
$ curl -X POST -H "Content-Type: application/json" -H "Authorization: Bearer f90b4bdf-a380-40d6-a6a7-5be28bd3ce99" -d '{"apiKey": "samsung", "tag": "cnn"}' localhost:8080/isTagAvailable {"message":"CustomTag is not available","tagAvailable":false}
这样就能实现仅对指定路径进行OAuth2安全过滤,同时公共路径不受影响。
内容的提问来源于stack exchange,提问作者Chloe
相关产品推荐
相关产品推荐

