通过 Cloudfront 请求 Spring 引导应用程序莫名其妙地失败,状态为 403

Request to Spring Boot application via Cloudfront fails inexplicably with 403 status

当我导航到 web.mysite.com 时,这是一个托管在 S3 中的静态 SPA,它有一个 iframe,它的 srcmysite.com/some/path,这是一个 Spring 引导Elastic Beanstalk 中的 MVC 应用程序。两者都支持 HTTPS 的 Cloudfront 发行版。此路径在应用程序中使用自定义资源解析器进行处理。这加载成功,但在 iframe 内容中有一个脚本标记正在寻找 mysite.com/some/path/thatsdifferent,由同一个解析器处理。

第二个请求失败并返回 403,我无法确定原因。直接在我的浏览器中导航到失败的 mysite.com/some/path/thatsdifferent 或使用 postman 成功,状态为 200。服务器配置为通过 CORS 配置允许来自 web.mysite.com 的请求(并且没有 CORS-related 错误消息)并且 Spring 安全配置为 permitAll 对 [=18] 的任何请求=] 无论身份验证如何。在 header x-cache: Error from cloudfront 之外没有响应 body 或错误消息。

如果我导航到 the-beanstalk-env-url.com/some/path,它会加载 html,然后成功加载 the-beanstalk-env-url.com/some/path/thatsdifferent 中的内容。

对几个不同但相似路径的请求成功。去一条绝对 100% 不存在的路径 returns a 404.

服务器日志显示请求已成功处理,Cloudfront 正在向客户端返回合理的响应。查看 Cloudfront 日志仅报告 403,没有任何其他信息。

几乎 100% 的 Cloudfront 403 错误文章和问题都涉及 S3,这不是这里失败的部分。

将 Cloudfront 分发允许的方法从 GET, HEAD 更改为 GET, HEAD, OPTIONS 会导致直接向 mysite.com/some/path/thatsdifferent 的请求开始失败并显示 invalid CORS request,已通过将 Accept, Authorization, Host, OriginReferer headers。这没有修复潜在的错误。

调整 org.springframework.security 的日志记录不会在发生失败请求时记录任何额外信息,我的应用程序安全配置不是导致错误的原因。

在我的 Route 53 环境中用负载均衡器替换 Cloudfront 后,场景按预期运行,所以问题肯定在 Cloudfront。

解决方案是将 Cloudfront Origin Protocol 策略从 HTTP Only 切换到 HTTPS Only

我不知道为什么这对脚本文件而不是 html 文件很重要,但是当我发现如果我尝试连接到 Beanstalk 环境 URL 通过 https,Chrome 警告我正在使用的证书是为导致问题的 Cloudfront 分发服务的域设置的。