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

SpringBoot、Nginx与Spring Security重定向异常问题求助

Spring Boot + Nginx 重定向异常问题排查与解决

问题现象

  • 访问路径 www.dental-admin.test/back-dental-admin/microlens-service/swagger-ui.html 时,Nginx将/back-dental-admin/前缀的请求转发至Spring Cloud Gateway(localhost:8080),Gateway再将/microlens-service/前缀的请求转发至对应微服务。
  • 预期行为:未登录时访问该路径,Spring Security应重定向至 www.dental-admin.test/back-dental-admin/microlens-service/login;登录后正常进入Swagger页面。
  • 异常情况:点击登录按钮后,重定向URL丢失/back-dental-admin/前缀,变为 www.dental-admin.test/microlens-service/login。
  • 调整后的新问题:配置forward-headers-strategy: framework并修改Nginx参数后,访问原路径直接触发重定向至 www.dental-admin.test/back-dental-admin/back-dental-admin/microlens-service/login,出现前缀重复,且无需点击登录就触发重定向。

现有配置文件

Nginx配置

server {
    listen 443 ssl;
    listen [::]:443 ssl;
    server_name www.dental-admin.test;
    ssl_certificate /etc/nginx/ssl/dental-admin.test+1.pem;
    ssl_certificate_key /etc/nginx/ssl/dental-admin.test+1-key.pem;

    location / {
        proxy_set_header Forwarded $http_forwarded;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header X-Forwarded-Host $host;
        proxy_set_header X-Forwarded-Port $server_port;

        proxy_pass http://localhost:3000/;

        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
    }

    location /back-dental-admin/ {
        proxy_set_header Forwarded $http_forwarded;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header X-Forwarded-Host $host;
        proxy_set_header X-Forwarded-Port $server_port;
        proxy_set_header X-Forwarded-Prefix /back-dental-admin/;

        proxy_pass http://localhost:8080/;
    }
}

Spring Cloud Gateway配置

server:
  port: 8080
spring:
  application:
    zipkin: http://localhost:9411
  cloud:
    gateway:
      globalcors:
        corsConfigurations:
          '[/**]':
            allowedOrigins: "https://www.dental-admin.test/"
            allowedHeaders: "*"
            allowedMethods: "*"
            allowCredentials: true
      discovery:
        locator:
          enabled: true
      routes:
        - id: auth-service-route
          uri: lb://auth-service
          predicates:
            - Path=/auth-service/**
          filters:
            - AuthFilter
            - RewritePath=/auth-service/(?<segment>.*), /$\{segment}
        - id: client-service-route
          uri: lb://client-service
          predicates:
            - Path=/client-service/**
          filters:
            - AuthFilter
            - RewritePath=/client-service/(?<segment>.*), /$\{segment}
        - id: user-service-route
          uri: lb://user-service
          predicates:
            - Path=/user-service/**
          filters:
            - AuthFilter
            - RewritePath=/user-service/(?<segment>.*), /$\{segment}    
        - id: microlens-service-route
          uri: lb://microlens-service
          predicates:
            - Path=/microlens-service/**
          filters:
            - RewritePath=/microlens-service/(?<segment>.*), /$\{segment}

微服务配置

server:
  port: ${PORT:${SERVER_PORT:0}}
  forward-headers-strategy: framework
spring:
  application:
    zipkin: http://localhost:9411
eureka:
  client:
    fetch-registry: true
    register-with-eureka: true
    service-url:
      default-zone: http://localhost:8761/eureka
  instance:
    instanceId: ${spring.application.name}:${vcap.application.instance_id:${spring.application.instance_id:${random.value}}}

原因分析

1. 前缀丢失的核心原因

Spring Security生成重定向URL时,未正确识别Nginx传递的X-Forwarded-Prefix(/back-dental-admin/)。微服务收到的请求路径已被Gateway通过RewritePath去掉了/microlens-service/前缀,导致Spring Security仅基于当前上下文(根路径/)生成重定向URL,最终Gateway转发时仅补上/microlens-service/,丢失了最外层的/back-dental-admin/。

2. 前缀重复的原因

同时在Gateway和微服务配置forward-headers-strategy: framework后,Gateway会先处理X-Forwarded-Prefix并将其添加到请求路径中,微服务再次读取该前缀并添加到重定向URL,导致两次拼接出现重复。

解决办法

步骤1:修正Nginx的X-Forwarded-Prefix配置

将location /back-dental-admin/中的X-Forwarded-Prefix值改为/back-dental-admin(去掉末尾斜杠),避免路径拼接时出现重复:

proxy_set_header X-Forwarded-Prefix /back-dental-admin;

步骤2:调整Spring Cloud Gateway配置

  • 启用网关的转发头处理,确保X-Forwarded-Prefix正确传递给微服务,同时避免网关重复添加前缀:
server:
  port: 8080
  forward-headers-strategy: framework # 添加该行,让网关处理转发头
spring:
  application:
    zipkin: http://localhost:9411
  cloud:
    gateway:
      globalcors:
        corsConfigurations:
          '[/**]':
            allowedOrigins: "https://www.dental-admin.test" # 去掉末尾斜杠,避免跨域问题
            allowedHeaders: "*"
            allowedMethods: "*"
            allowCredentials: true
      discovery:
        locator:
          enabled: true
      routes:
        # 其他路由保持不变
        - id: microlens-service-route
          uri: lb://microlens-service
          predicates:
            - Path=/microlens-service/**
          filters:
            - RewritePath=/microlens-service/(?<segment>.*), /$\{segment}

步骤3:微服务配置调整与Spring Security优化

  1. 保留forward-headers-strategy: framework,确保微服务读取转发头:
server:
  port: ${PORT:${SERVER_PORT:0}}
  forward-headers-strategy: framework
  1. 在微服务的Spring Security配置中,显式启用转发头处理,让Spring Security基于X-Forwarded-Prefix生成正确的重定向URL:
    如果是WebFlux架构(适配Gateway的响应式模型):
@Configuration
@EnableWebFluxSecurity
public class SecurityConfig {

    @Bean
    public SecurityFilterChain securityFilterChain(ServerHttpSecurity http) throws Exception {
        http
            .forwardedHeaders() // 启用转发头解析
            .and()
            .authorizeExchange(exchanges -> exchanges
                .pathMatchers("/swagger-ui/**", "/v3/api-docs/**").permitAll()
                .anyExchange().authenticated()
            )
            .formLogin(form -> form
                .loginPage("/login")
                .permitAll()
            );
        return http.build();
    }
}

如果是Servlet架构:

@Configuration
@EnableWebSecurity
public class SecurityConfig {

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http
            .headers(headers -> headers.frameOptions().sameOrigin())
            .forwardedHeaders() // 启用转发头解析
            .and()
            .authorizeHttpRequests(auth -> auth
                .requestMatchers("/swagger-ui/**", "/v3/api-docs/**").permitAll()
                .anyRequest().authenticated()
            )
            .formLogin(form -> form
                .loginPage("/login")
                .permitAll()
            );
        return http.build();
    }
}

步骤4:验证重定向逻辑

重启Nginx、Gateway和微服务后,访问www.dental-admin.test/back-dental-admin/microlens-service/swagger-ui.html:

  • 未登录时应自动重定向至www.dental-admin.test/back-dental-admin/microlens-service/login
  • 点击登录按钮后,验证重定向URL是否保留完整前缀,登录成功后正常进入Swagger页面

内容的提问来源于stack exchange,提问作者Juan Jose Garcia

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.21 17:55:06