Spring Boot3+Spring Security6中requestMatchers引发403 Forbidden问题求助
Spring Security 6 403 Forbidden问题排查与解决
我已多日尝试解决Spring Security 6的权限问题,查阅官方文档和多个教程仍未找到原因。目前访问/resource/**端点正常返回200,但访问/api/**、/db/**这类配置了权限的端点时,始终返回403 Forbidden。已确认从application.properties读取的账号密码正确,排除配置读取问题。
相关代码
WebSecurityConfigurer.class
package com.transfer.market.configuration; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.core.userdetails.User; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.security.provisioning.InMemoryUserDetailsManager; import org.springframework.security.web.SecurityFilterChain; import org.springframework.security.web.access.expression.WebExpressionAuthorizationManager; @Configuration @EnableWebSecurity public class WebSecurityConfigurer { private final String ADMIN; private final String ADMIN_PASS; private final String SUPER; private final String SUPER_PASS; @Autowired public WebSecurityConfigurer(AppSecurityExternalConfig appSecurityExternalConfig) { this.ADMIN = appSecurityExternalConfig.getUser().getAdmin(); this.ADMIN_PASS = appSecurityExternalConfig.getPassword().getAdmin(); this.SUPER = appSecurityExternalConfig.getUser().getSup(); this.SUPER_PASS = appSecurityExternalConfig.getPassword().getSup(); } @Bean public UserDetailsService users() { UserDetails admin = User.builder() .username(ADMIN) .password(encoder().encode(ADMIN_PASS)) .roles("ADMIN") .build(); UserDetails sup = User.builder() .username(SUPER) .password(encoder().encode(SUPER_PASS)) .roles("ADMIN", "DBA") .build(); return new InMemoryUserDetailsManager(admin, sup); } @Bean public SecurityFilterChain web(HttpSecurity http) throws Exception { http.csrf().disable() .authorizeHttpRequests(auth -> auth .requestMatchers("/resource/**").permitAll() .requestMatchers("/api/**").hasAnyRole("ADMIN", "DBA") .requestMatchers("/db/**") .access(new WebExpressionAuthorizationManager("hasRole('ADMIN') and hasRole('DBA')")) .anyRequest().denyAll() ); return http.build(); } @Bean public static BCryptPasswordEncoder encoder() { return new BCryptPasswordEncoder(); } }
AppSecurityExternalConfig.class
package com.transfer.market.configuration; import lombok.Data; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.context.annotation.Configuration; import org.springframework.stereotype.Component; @Data @Configuration @ConfigurationProperties(prefix = "config.security") public class AppSecurityExternalConfig { private User user; private Password password; @Data @Component @ConfigurationProperties(prefix = "user") public static class User { private String user; private String admin; private String sup; } @Data @Component @ConfigurationProperties(prefix = "password") public static class Password { private String user; private String admin; private String sup; } }
application.properties
... # Security: config.security.user.admin=admin config.security.password.admin=pass config.security.user.sup=super config.security.password.sup=pass ...
PlayerController.class
@RestController @Validated public class PlayerController { private final PlayerService playerService; @Autowired public PlayerController(PlayerService playerService) { this.playerService = playerService; } @PostMapping("/api/players") public ResponseEntity<Player> addSingle(@RequestBody @Valid Player player) { return new ResponseEntity<>(playerService.addSingle(player), HttpStatus.CREATED); } ...
问题原因及修复方案
1. 缺少认证方式配置
当前SecurityFilterChain仅定义了权限规则,但未指定任何认证机制(如HTTP Basic、表单登录)。Spring Security无法对请求用户进行身份验证,直接返回403。
修复:在web方法中添加HTTP Basic认证配置:
@Bean public SecurityFilterChain web(HttpSecurity http) throws Exception { http.csrf().disable() .authorizeHttpRequests(auth -> auth .requestMatchers("/resource/**").permitAll() .requestMatchers("/api/**").hasAnyRole("ADMIN", "DBA") .requestMatchers("/db/**") .access(new WebExpressionAuthorizationManager("hasRole('ADMIN') and hasRole('DBA')")) .anyRequest().denyAll() ) // 添加HTTP Basic认证 .httpBasic(Customizer.withDefaults()); return http.build(); }
2. 配置属性绑定错误
AppSecurityExternalConfig的内部类User和Password额外添加了@Component和@ConfigurationProperties,与外层类的prefix = "config.security"冲突,导致配置路径解析错误(例如config.security.user.admin会被解析为user.admin,无法正确读取)。
修复:移除内部类上的@Component和@ConfigurationProperties注解:
@Data @Configuration @ConfigurationProperties(prefix = "config.security") public class AppSecurityExternalConfig { private User user; private Password password; @Data public static class User { private String user; private String admin; private String sup; } @Data public static class Password { private String user; private String admin; private String sup; } }
内容的提问来源于stack exchange,提问作者andy489
相关产品推荐
相关产品推荐

