You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Apache反向代理下Spring Boot-Spring Security路径配置问题

我来帮你搞定这个问题,咱们先理清楚问题根源,再一步步解决:

问题本质分析

你碰到的两个问题其实是同一个核心原因:你的认证服务Spring Boot应用不知道自己是在/auth这个代理路径下对外提供服务的

  • 第一个阶段:认证服务生成静态资源URL时,默认用自己的根路径,所以输出了/resources/jquery.min.js,而不是带/auth前缀的正确路径;
  • 第二个阶段:加了ProxyPreserveHost On后,Spring Security生成重定向URL时,依然没意识到需要带上/auth前缀,直接跳转到了根路径的/login,导致404。

分步解决方案

我们需要从后端服务配置和Apache代理配置两方面配合调整,让后端明确自己的代理上下文:

1. 调整认证服务的application.properties

给认证服务添加上下文路径,这样所有内部生成的URL(包括静态资源、重定向地址)都会自动带上/auth前缀:

# 让认证服务知道自己的上下文路径是/auth,和Apache的代理路径保持一致
server.servlet.context-path=/auth

# 启用转发头处理,让Spring Boot识别外部请求的协议、端口等信息
server.use-forward-headers=true

# 如果你的Spring Security版本是5.7及以上,加上这个配置增强转发头兼容性(可选)
spring.security.filter.order=-100
server.forward-headers-strategy=NATIVE

2. 优化Apache虚拟主机配置

去掉ProxyPreserveHost On(这个配置会让后端忽略代理路径,反而加重问题),同时调整代理路径和后端的上下文路径匹配,确保转发头正确传递:

<VirtualHost *:80>
ServerName www.website.com
RewriteEngine on
RewriteCond %{SERVER_NAME} =www.website.com
RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [END,NE,R=permanent]
</VirtualHost>

<VirtualHost *:443>
SSLEngine on
SSLProxyEngine on
ServerName www.website.com

# 传递转发头,让Spring Boot知道外部请求用的是HTTPS和443端口
RequestHeader set X-Forwarded-Proto https
RequestHeader set X-Forwarded-Port 443

# 代理认证服务:注意这里要和后端的context-path对应,把/auth转发到后端的/auth路径
ProxyPass /auth https://127.0.0.1:8081/auth
ProxyPassReverse /auth https://127.0.0.1:8081/auth

# 代理资源服务,保持原有配置即可
ProxyPass /api https://127.0.0.1:8082
ProxyPassReverse /api https://127.0.0.1:8082

# 代理前端服务,保持原有配置即可
ProxyPass / https://127.0.0.1:8084/
ProxyPassReverse / https://127.0.0.1:8084/

SSLCertificateFile /etc/letsencrypt/live/www.website.com/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/www.website.com/privkey.pem
Include /etc/letsencrypt/options-ssl-apache.conf
</VirtualHost>

3. 验证效果

重启Apache和认证服务之后:

  • 访问https://www.website.com/auth/oauth/authorize会正确重定向到https://www.website.com/auth/login,不会丢失/auth前缀;
  • 登录页的静态资源(比如/auth/resources/jquery.min.js)会被正确请求,再也不会出现404的情况。

为什么之前的配置不行?

  • 初始配置里,认证服务没有设置context-path,所以它生成的所有URL都是以根路径开头,自然不会带/auth前缀;
  • 加上ProxyPreserveHost On后,后端服务虽然知道了外部的域名,但还是不知道自己处于/auth路径下,所以重定向URL依然是根路径的/login
  • 而通过设置server.servlet.context-path=/auth,相当于从后端根源上定义了自己的上下文路径,所有生成的URL都会自动带上这个前缀,再配合Apache的正确代理路径,两个问题就都解决了。

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

火山引擎 最新活动