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




