You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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")避免扫描冲突。

验证步骤

  1. 启动项目后,访问http://localhost:8090/testBruh,应直接返回"YO"(已配置permitAll)。
  2. 访问网关路由接口(如/account-service/**),通过Postman添加Basic Auth认证(用户名javainuse、密码javainuse),或浏览器登录表单输入账号密码,均能正常访问接口。

内容的提问来源于stack exchange,提问作者ralzohairi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.16 05:55:47