Spring Security配置异常:所有请求返回401未授权
Spring Boot网关集成Spring Security内存认证401问题解决
问题描述
在Spring Boot网关项目中集成Spring Security实现内存认证,无论使用登录表单还是Postman发起请求,全部返回401未授权。尝试过添加组件扫描、调整过滤器顺序、排除自动配置、切换明文/加密密码等方案,均无效。
项目配置代码
Application类
@EnableEurekaClient @SpringBootApplication @ComponentScan(basePackages = "sdp.training.gatewayservice.security") public class GatewayServiceApplication { public static void main(String[] args) { SpringApplication.run(GatewayServiceApplication.class, args); } }
Security配置类
@Configuration @EnableWebSecurity @EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true) public class SecurityConfiguration extends WebSecurityConfigurerAdapter { @Override public void configure(AuthenticationManagerBuilder auth) throws Exception { // 加密密码字符串 String encodedPassword = passwordEncoder().encode("javainuse"); // 创建用户对象 UserDetails user = User.builder() .username("javainuse") .password(encodedPassword) .roles("USER") .build(); // 内存认证配置(原写法存在错误) auth.inMemoryAuthentication()// .passwordEncoder(NoOpPasswordEncoder.getInstance()) .withUser(user) .passwordEncoder(passwordEncoder()); } @Override public void configure(HttpSecurity http) throws Exception { http.csrf().disable(); http.authorizeRequests() .antMatchers("/testBruh").permitAll() .anyRequest().authenticated() .and().formLogin().permitAll() .and().httpBasic(); } @Bean public PasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(); } }
测试控制器
@RestController @RequestMapping(value = "/testBruh") public class TestController { @GetMapping public ResponseEntity<Object> getAccounts() { return ResponseEntity.status(HttpStatus.OK).body("YO"); } }
application.properties配置
spring.application.name: gateway-service server.port: 8090 # spring.autoconfigure.exclude=org.springframework.boot.autoconfigure.security.SecurityAutoConfiguration # spring.security.user.name=admin # spring.security.user.password=123456 # spring.security.user.roles=manager spring.security.filter.order=10 spring.main.allow-bean-definition-overriding=true spring.cloud.gateway.routes[0].id=accountService spring.cloud.gateway.routes[0].uri=lb://account-service spring.cloud.gateway.routes[0].predicates[0].name=Path spring.cloud.gateway.routes[0].predicates[0].args.pattern=/account-service/** spring.cloud.gateway.routes[0].filters[0]=StripPrefix=1 spring.cloud.gateway.routes[1].id=blogService spring.cloud.gateway.routes[1].uri=lb://blog-service spring.cloud.gateway.routes[1].predicates[0].name=Path spring.cloud.gateway.routes[1].predicates[0].args.pattern=/blog-service/** spring.cloud.gateway.routes[1].filters[0]=StripPrefix=1
问题原因及解决方法
核心问题:内存认证配置链式调用顺序错误
原configure(AuthenticationManagerBuilder auth)方法中,passwordEncoder()的位置错误,应该先为内存认证指定密码编码器,再添加用户信息。正确写法如下:
@Override public void configure(AuthenticationManagerBuilder auth) throws Exception { String encodedPassword = passwordEncoder().encode("javainuse"); UserDetails user = User.builder() .username("javainuse") .password(encodedPassword) .roles("USER") .build(); // 调整顺序:先设置密码编码器,再添加用户 auth.inMemoryAuthentication() .passwordEncoder(passwordEncoder()) .withUser(user); }
也可以使用更简洁的链式写法:
@Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { auth.inMemoryAuthentication() .passwordEncoder(passwordEncoder()) .withUser("javainuse") .password(passwordEncoder().encode("javainuse")) .roles("USER"); }
可选优化:移除多余的组件扫描
@SpringBootApplication注解默认扫描当前类所在包及其子包,若SecurityConfiguration位于sdp.training.gatewayservice.security包下,而GatewayServiceApplication在sdp.training.gatewayservice包下,默认扫描已覆盖Security配置类,可移除@ComponentScan(basePackages = "sdp.training.gatewayservice.security")避免扫描冲突。
验证步骤
- 启动项目后,访问
http://localhost:8090/testBruh,应直接返回"YO"(已配置permitAll)。 - 访问网关路由接口(如
/account-service/**),通过Postman添加Basic Auth认证(用户名javainuse、密码javainuse),或浏览器登录表单输入账号密码,均能正常访问接口。
内容的提问来源于stack exchange,提问作者ralzohairi
相关产品推荐
相关产品推荐

