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优化
- 保留
forward-headers-strategy: framework,确保微服务读取转发头:
server: port: ${PORT:${SERVER_PORT:0}} forward-headers-strategy: framework
- 在微服务的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
相关产品推荐
相关产品推荐

