为什么我的 HTTP Origin 标头与 request.base_url 不匹配以及如何修复?

ada*_*lfo 8 ruby ruby-on-rails http cors

你好,这是我在这里的第一篇文章!

我已经尝试调试这个问题几天了,但无法弄清楚。当我向 Rails api 发出发布请求时,我收到了以前从未见过的错误:

Started POST "/owners" for ::1 at 2021-01-12 11:24:15 -0500
   (1.0ms)  SELECT "schema_migrations"."version" FROM "schema_migrations" ORDER BY "schema_migrations"."version" ASC
Processing by OwnersController#create as */*
  Parameters: {"email"=>"adam", "password"=>"[FILTERED]", "owner"=>{"email"=>"adam"}}
HTTP Origin header (http://localhost:3000) didn't match request.base_url (http://localhost:3001)
Completed 422 Unprocessable Entity in 0ms (ActiveRecord: 1.8ms | Allocations: 476)


  
ActionController::InvalidAuthenticityToken (ActionController::InvalidAuthenticityToken):
Run Code Online (Sandbox Code Playgroud)

就像我说的,我以前从未见过这种情况,我不知道我是如何造成它的。我没有使用代理服务器,我在这个项目中尝试的唯一可能搞砸的新事情是我安装了 devise gem,但决定不使用它并删除它。

我尝试过的事情:

确保我没有待处理的迁移:

检查我的路线:

Rails.application.routes.draw do
  resources :owners
  resources :dogs
  post 'login', to: 'sessions#create'
end
Run Code Online (Sandbox Code Playgroud)

然后我认为这可能是一个cors问题:

require_relative 'boot'

require 'rails/all'

# Require the gems listed in Gemfile, including any gems
# you've limited to :test, :development, or :production.
Bundler.require(*Rails.groups)

module Backend
  class Application < Rails::Application
    # Initialize configuration defaults for originally generated Rails version.
    config.load_defaults 6.0

    # Settings in config/environments/* take precedence over those specified here.
    # Application configuration can go into files in config/initializers
    # -- all .rb files in that directory are automatically loaded after loading
    # the framework and any gems in your application.
    config.api_only = true

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

  end
end

Run Code Online (Sandbox Code Playgroud)

然后我尝试在谷歌上搜索有关无效真实性令牌和http原始标头的内容,但找不到有用的解决方案或我可以理解的解决方案。

(最后一点:我尝试将其从发布请求更改为获取请求,它有效,但发布会导致错误)

感谢您提前提供任何建议

Fer*_*osh 14

就我而言,问题出在虚拟主机的 Ngixn 设置上。在以下位置找到答案:https://github.com/rails/rails/issues/22965#issuecomment-169956605

通过在 Nginx 中添加更多标头(X-Forwarded-Ssl on、X-Forwarded-Port 443 和 X-Forwarded-Host 主机名)进行修复

这是编辑后该部分的样子:

    location @app {
      proxy_pass http://app;
      proxy_set_header X-Real-IP $remote_addr;
      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
      proxy_set_header X-Forwarded-Proto https;
      proxy_set_header X-Forwarded-Server $host;
      proxy_set_header Host $http_host;
      proxy_redirect off;
    }
Run Code Online (Sandbox Code Playgroud)


bas*_*rd7 0

我认为这是一个 CSRF(跨站请求伪造)问题。Rails 正在尝试阻止向您的控制器发出无效请求。它正在您的请求标头中寻找一个authenticity_token,该令牌通过表单中的隐藏元素进入请求html.erb,以将请求发送到特定路径。当您使用 Rails 作为 API 时,这些令牌不存在。

有多种策略可以防止这种异常,并且都有不同的安全隐患。这是一个很好的起点: 不禁用 CSRF 保护的 Rails API 设计

  • 这就是我一直在寻找的解决方案!我在应用程序控制器中使用了``skip_before_action :verify_authenticity_token```并且它起作用了。非常感谢 (4认同)
  • 这是一种危险的做法。对所有控制器方法使用 verify_authenticity_token 并不安全。还有其他方法。 (3认同)