部署至GCP App Engine后,Spring Security配置的HSTS响应头为何丢失?
核心根因
GCP App Engine 标准环境采用SSL终止架构,请求流转逻辑如下:
- 外部客户端与App Engine边缘负载均衡的通信为HTTPS(符合你
secure: always的配置要求) - 负载均衡解密HTTPS流量后,使用内部HTTP协议将请求转发至Java应用实例
Spring Security 的HSTS头默认仅在HttpServletRequest.isSecure()返回true(即判定请求为HTTPS)时才会添加。由于应用接收到的内部请求为HTTP协议,被判定为非安全连接,因此跳过HSTS头输出。
本地测试时你直接模拟HTTPS请求,应用可直接识别安全连接,因此HSTS可正常返回。
解决方案
推荐方案:开启转发头解析
GCP App Engine 负载均衡会自动向转发请求注入X-Forwarded-Proto头,值为外部客户端原始请求的协议(此处为https)。只需让Spring Boot信任并解析该头,即可正确识别原始请求的HTTPS属性。
在application.properties(或对应YML配置)中添加以下配置:
server.forward-headers-strategy=framework
该配置会自动注册ForwardedHeaderFilter,修正请求的协议、端口等元数据,Spring Security会自动判定当前为HTTPS环境,正常输出HSTS头。
兜底方案:强制触发HSTS返回
若因版本限制无法使用转发头配置,可直接修改Spring Security配置,跳过HSTS的安全连接校验:
@Override protected void configure(HttpSecurity http) throws Exception { http.headers() .httpStrictTransportSecurity() .requestMatcher(new AnyRequestMatcher()) .maxAgeInSeconds(31536000) .includeSubDomains(true); }
该方案不会引入安全风险:你已通过App Engine配置强制所有外部HTTP请求重定向至HTTPS,仅HTTPS响应会返回HSTS头,符合HSTS的使用规范。
验证方式
部署后执行以下命令检查响应头:
curl -I https://<你的App Engine服务域名>
确认输出中存在Strict-Transport-Security: max-age=31536000; includeSubDomains字段即可。
内容的提问来源于stack exchange,提问作者Kian Aghaei

