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

Posted

技术标签:

【中文标题】通过 Cloudfront 对 Spring Boot 应用程序的请求莫名其妙地失败,状态为 403【英文标题】:Request to Spring Boot application via Cloudfront fails inexplicably with 403 status 【发布时间】:2020-03-06 16:51:27 【问题描述】:

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

第二个请求失败并返回 403,我无法确定原因。直接在我的浏览器中导航到失败的mysite.com/some/path/thatsdifferent 或使用邮递员成功,状态为 200。服务器配置为允许来自 web.mysite.com 通过 CORS 配置的请求(并且没有与 CORS 相关的错误消息),并且 Spring Security 配置为 permitAll 任何对 /some/** 的请求,无论身份验证如何。除了标头 x-cache: Error from cloudfront 之外,没有响应正文或错误消息。

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

对几个不同但相似的路径的请求成功。转到绝对 100% 不存在的路径会返回 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 标头列入白名单来解决。这并没有解决根本错误。

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

在我的 Route 53 环境中将 Cloudfront 替换为负载均衡器后,该方案按预期工作,因此问题肯定出在 Cloudfront。

【问题讨论】:

增加你的 spring 安全日志和重新部署/重新测试。这有望为您提供有关故障性质的更多信息。 @AndyN 将级别增加到 DEBUG 不会记录任何内容。 Spring 正在按应有的方式处理请求,这意味着它没有被我的应用程序阻止。 【参考方案1】:

解决方案是将 Cloudfront 源协议策略从 HTTP Only 切换到 HTTPS Only

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

【讨论】:

我已经按照你的建议做了。但它现在部分起作用了。一些端点使用 200,而其他端点使用 502。不知道为什么。你有什么建议吗? 我添加了一个新证书并与 EBS 建立了连接,引发了负载均衡器。我看到所有请求都会抛出 https。但是现在我只在具有弹簧安全性的端点上获得 403

以上是关于通过 Cloudfront 对 Spring Boot 应用程序的请求莫名其妙地失败,状态为 403的主要内容,如果未能解决你的问题,请参考以下文章

通过 CloudFront 进行私有 HTTP 实时流式传输

Cloudfront 无法访问部署在 EBS 上的 Spring Boot 上的安全端点

CloudFront + EC2 + Apache + PHP

在CloudFront访问上触发RDS lambda

是否可以通过 CloudFront CDN 进行 AWS 内容路由?

开始使用 Python 进行安全 AWS CloudFront 流式传输