Spring Security OAuth2始终返回403问题排查求助
解决方案:Spring Boot OAuth2 配置——保护所有端点,放行特定接口
看起来你已经在搭建OAuth2授权服务器了,要实现「除认证、创建账户和部分信息类端点外,所有接口都需要安全保护」的需求,咱们可以通过授权服务器配置+全局HTTP安全配置两步来完成,下面是完整的实现方案:
1. 完善OAuth2授权服务器配置
首先补全你未写完的OAuth2Config,这里包含客户端信息、令牌存储、端点配置等核心内容:
@Configuration @EnableAuthorizationServer public class OAuth2Config extends AuthorizationServerConfigurerAdapter { @Autowired private AuthenticationManager authenticationManager; @Autowired private MongoTokenStore tokenStore; // 注入自定义用户详情服务,用于验证用户身份 @Autowired private UserDetailsService userDetailsService; @Override public void configure(ClientDetailsServiceConfigurer clients) throws Exception { // 这里配置你的OAuth2客户端信息,生产环境建议从数据库读取,示例用内存存储 clients.inMemory() .withClient("your-app-client") .secret("{noop}your-client-secret") // 测试用明文,生产环境替换为BCrypt加密后的密文 .authorizedGrantTypes("password", "refresh_token") // 支持密码模式和刷新令牌 .scopes("read", "write") // 客户端权限范围 .accessTokenValiditySeconds(3600) // 访问令牌有效期1小时 .refreshTokenValiditySeconds(86400); // 刷新令牌有效期1天 } @Override public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception { endpoints .tokenStore(tokenStore) // 用MongoDB存储令牌 .authenticationManager(authenticationManager) // 绑定认证管理器,支持密码模式 .userDetailsService(userDetailsService); // 刷新令牌时验证用户有效性 } @Override public void configure(AuthorizationServerSecurityConfigurer security) throws Exception { // 允许公开访问令牌密钥端点,允许认证用户检查令牌,允许表单提交获取令牌 security .tokenKeyAccess("permitAll()") .checkTokenAccess("isAuthenticated()") .allowFormAuthenticationForClients(); } }
2. 配置全局HTTP安全规则
这一步是实现「大部分端点保护,少数放行」的核心,根据你使用的Spring Security版本,分两种写法:
写法一:Spring Security 5.7及之前版本(使用WebSecurityConfigurerAdapter)
@Configuration @EnableWebSecurity public class WebSecurityConfig extends WebSecurityConfigurerAdapter { @Autowired private UserDetailsService userDetailsService; // 密码编码器,生产环境必须用BCrypt等安全加密方式 @Bean public PasswordEncoder passwordEncoder() { // 测试用明文编码器,生产替换为 new BCryptPasswordEncoder() return NoOpPasswordEncoder.getInstance(); } @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder()); } // 暴露AuthenticationManager给OAuth2配置使用 @Override @Bean public AuthenticationManager authenticationManagerBean() throws Exception { return super.authenticationManagerBean(); } @Override protected void configure(HttpSecurity http) throws Exception { http .csrf().disable() // REST API通常关闭CSRF防护 .authorizeRequests() // 放行不需要认证的端点:根据你的实际接口路径调整 .antMatchers("/api/auth/**", "/api/users/register", "/api/public/**").permitAll() // 其他所有端点必须经过认证 .anyRequest().authenticated() .and() .sessionManagement() .sessionCreationPolicy(SessionCreationPolicy.STATELESS); // REST API用无状态会话,不创建Session } }
写法二:Spring Security 5.7+ 或 Spring Boot 2.7+(推荐,WebSecurityConfigurerAdapter已过时)
@Configuration @EnableWebSecurity public class WebSecurityConfig { @Autowired private UserDetailsService userDetailsService; @Bean public PasswordEncoder passwordEncoder() { // 生产环境推荐用BCryptPasswordEncoder return new BCryptPasswordEncoder(); } // 暴露AuthenticationManager @Bean public AuthenticationManager authenticationManager(AuthenticationConfiguration authConfig) throws Exception { return authConfig.getAuthenticationManager(); } @Bean public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { http .csrf(csrf -> csrf.disable()) .authorizeHttpRequests(auth -> auth // 放行的端点列表,按需调整 .requestMatchers("/api/auth/login", "/api/users/register", "/api/public/info").permitAll() .anyRequest().authenticated() ) .sessionManagement(session -> session .sessionCreationPolicy(SessionCreationPolicy.STATELESS) ); return http.build(); } }
关键注意点
- 放行端点调整:你需要根据自己项目的实际接口路径,修改
antMatchers或requestMatchers里的内容,确保注册、登录、公开信息类接口都被permitAll()放行。 - 密码加密:生产环境绝对不能用
NoOpPasswordEncoder,必须使用BCryptPasswordEncoder或更安全的加密方式,注册用户时要提前对密码进行加密。 - 无状态会话:设置
SessionCreationPolicy.STATELESS符合REST API的无状态设计,避免服务器存储会话信息。 - Spring Boot 3.x 注意:
@EnableAuthorizationServer在Spring Boot 3.x中已过时,官方推荐使用Spring Authorization Server替代,如果是新项目建议直接用新组件。
内容的提问来源于stack exchange,提问作者Monta
相关产品推荐
相关产品推荐

