首页 > 解决方案 > Ruby on Rails:提交表单时“您想要的更改被拒绝”

问题描述

ruby 3.0.1 rails 6.1.2 'devise', '~> 4.7', '>= 4.7.3'

我处于一个非常不寻常的境地。我正在将 Rails 安装从一台服务器迁移到另一台服务器。我相信我已经完成了大约 95% 的工作,刚刚恢复了生产数据库。

但是,任何涉及表单提交的事情,包括用户注册和登录,都会给我错误页面:

The change you wanted was rejected.

Maybe you tried to change something you didn't have access to.

服务器日志给了我更多帮助:

Completed 422 Unprocessable Entity in 2ms (Allocations: 433)
FATAL -- ActionController::InvalidAuthenticityToken

这让我很困惑。因为我确实重新生成了 master.key 和 credentials.yml.enc 并通过RAILS_MASTER_KEY环境变量使 master.key 的内容可用。这意味着表单具有适当的<input type="hidden" name="authenticity_token" value="<removed for stack_overflow>">包含以防止跨站点脚本攻击。

我认为这与会话没有任何关系,因为即使是用户注册也会受此影响。我正在使用设计进行身份验证。

但是……现在我碰壁了。从这里无处可去。有谁知道出了什么问题?

更新 1

添加skip_before_action :verify_authenticity_token确实让我跳过了这个问题。作为解决方案,我不满意。

更新 2

我有这些元标记。

<%= csrf_meta_tags %>
<%= csp_meta_tag %>

标签: ruby-on-railsrubyauthentication

解决方案


我羞于承认。但是 nginx 没有正确配置。一旦我到达了rails的临界点,我终于开始问这怎么可能发生。

这是交易。在内部,rails 使用 http 来访问各种端点。我有一个 nginx 重定向块,如下所示:

 server {
  listen 80 default_server;

  server_name _;

  return 301 https://$host$request_uri;
}

这意味着每次内部端点在 http 上被点击时,它都会变成带有 301 的 https ......这总是一个 GET。一旦我使用config.force_ssl = truein production.rb,我只需要重做我的 ngix 配置来支持它。

这是工作配置。

location / {
  proxy_set_header Host $http_host;
  proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
  proxy_set_header X-Forwarded-Proto https;
  proxy_redirect off;
  proxy_pass http://app:3000;
}

它看起来像身份验证令牌问题的原因是,一旦请求作为 GET 发送,它就是一个不可处理的实体。即使我可以在浏览器检查中看到它,令牌到达那里时也可能是 nil 或其他东西。只是动词错了。


推荐阅读