AWS Elastic Beanstalk 上的 Rails 应用程序返回 422 并显示“无法验证 csrf 令牌”

Posted

技术标签:

【中文标题】AWS Elastic Beanstalk 上的 Rails 应用程序返回 422 并显示“无法验证 csrf 令牌”【英文标题】:Rails app on AWS Elastic Beanstalk returning 422 with "Can't verify csrf token" 【发布时间】:2019-07-01 02:22:34 【问题描述】:

我有一个使用 Puma 和 nginx 的 Rails 5.1.4 应用程序,它已经在 Elastic Beanstalk (AWS) 上的生产环境中运行了一段时间。我最近在同一个地方打开了一个新的 QA 环境,并且在 html 调用(API 调用正常)上的 POST 请求中不断收到 422 错误,并显示消息“无法验证 csrf 令牌”。每个配置值都相同或等效。

我添加了必要的标签并检查了真实性令牌值。在<head> 标签下我有:

<meta name="csrf-param" content="authenticity_token">
<meta name="csrf-token" content="acYjbDMNDXsw+mHN7pM/4XldHungS9kDlkkTT1moNQaf1y7wRhLJhOVb7GTMDieLU4kGc7yWlOch4DlG/z/A8g==">

在我的登录表单上,我有以下内容:

<input type="hidden" name="authenticity_token" value="acYjbDMNDXsw+mHN7pM/4XldHungS9kDlkkTT1moNQaf1y7wRhLJhOVb7GTMDieLU4kGc7yWlOch4DlG/z/A8g==">

在日志中我收到参数:

Parameters: "utf8"=>"✓", "authenticity_token"=>"acYjbDMNDXsw+mHN7pM/4XldHungS9kDlkkTT1moNQaf1y7wRhLJhOVb7GTMDieLU4kGc7yWlOch4DlG/z/A8g==", "user"=>"email"=>"someemail@mail.com", "password"=>"[FILTERED]", "remember_me"=>"1"

我还有rack-cors gem 和以下配置:

    config.middleware.insert_before 0, Rack::Cors do
      allow do
        origins '*'
        resource '*', headers: :any, methods: [:get, :post, :options]
      end
    end

我已经尝试解决这个问题几天了,我对如何继续感到很迷茫,关于可能导致此问题的任何想法?任何其他可能有助于找出问题的信息?

【问题讨论】:

不是api还是内部调用? 内部调用,更新信息 【参考方案1】:

我的第一个猜测是涉及到一些 HTML 缓存,因为令牌不同。我在 Rails 后端运行 Varnish 时看到过类似的行为,你有类似 Rack::Cache 或 Nginx 的代理缓存之类的东西吗?

【讨论】:

有趣的是,您在 QA 中观察到了这个错误,并且它正在生产中工作。 这确实很有趣。对不起,我在 OP 上粘贴了错误的键,令牌实际上是匹配的,这让我很难弄清楚这个问题:( 是时候再猜一次了,如果在控制器中你收到正确的 CSRF 令牌,显示在 HTML 中并且不涉及缓存,那么 Rails 无法在会话存储中找到令牌 - - 这是它检查 CSRF 令牌是否正确的地方。如果这个理论是正确的,那么您将无法登录,因为会话 cookie 不会被持久化。您可以尝试完全禁用 CSRF 检查——而不是在生产中! -- 并检查您是否可以登录。【参考方案2】:

所以,如果它在将来对某人有所帮助,我设法解决了这个问题,虽然不是完全。在我的 nginx 配置中,我有这一行:

server_name *.myappdomain.com;

myappdomain 是我的生产域。我试图使用我的 elasticbeanstalk url 登录,类似于http://myapp-stage.region.elasticbeanstalk.com。我在路由 53 上向我的 DNS 中添加了一个条目,将别名 stage.myappdomain.com 添加到弹性 beanstalk URL 并且它起作用了。我怀疑更多地使用 nginx 配置也会以更好的方式解决这个问题。

【讨论】:

【参考方案3】:

这可能发生的另一个原因:如果 nginx 使用纯 http 连接到 rails 服务器,默认情况下,如果它们被标记为安全(它们应该是),nginx 将不允许 rails 访问 cookie。有多种方法可以配置 NGINX 以通过它们 - 可以在 the unix & linux stackexchange 上找到一个很好的总结

(请注意,这可能不是唯一可能发生的情况,因此请尽可能检查堆栈每一层的配置)

【讨论】:

以上是关于AWS Elastic Beanstalk 上的 Rails 应用程序返回 422 并显示“无法验证 csrf 令牌”的主要内容,如果未能解决你的问题,请参考以下文章

如何避免 AWS Elastic Beanstalk 上的 TooManyApplicationVersion 异常?

反应:AWS Elastic Beanstalk 上的 502 错误网关

AWS Elastic Beanstalk 上的 Wordpress

AWS Elastic Beanstalk 上的 Spring Boot 并记录到文件

AWS Elastic Beanstalk 上的 Django manage.py

如何获取命令以从 Elastic Beanstalk 上的 Dockerfile.aws.json 运行?