使用 NGINX 和 Rails 登录时的 ActionController::InvalidAuthenticityToken

csw*_*abe 2 ruby-on-rails nginx csrf ruby-on-rails-6

我实现了一个反向代理来访问我的 Rails 应用程序。但是,每当我尝试登录时,ActionController::InvalidAuthenticityToken无论是管理员帐户还是非管理员帐户,我每次都会遇到错误。我读到你需要包含proxy_set_header X-Forwarded-Proto https;它才能工作,但到目前为止对我来说还没有。

这是我当前的 nginx conf 文件

upstream backend{
        server localhost:3000;
    }
    server {
        listen       80;
        listen  443 ssl;
        server_name  localhost;
        ssl_certificate localhost.cert;
        ssl_certificate_key localhost.key;

        location / {
            root   html;
            index  index.html index.htm;
            proxy_pass http://backend;
            proxy_set_header X-Forwarded-Proto https;
            proxy_set_header X-Forwarded-Ssl on;
        }
Run Code Online (Sandbox Code Playgroud)

当我使用 localhost:3000(这是我的 Rails 应用程序的主机名)登录时,它会登录。所以问题出在 nginx 上。这里还有我来自 Rails 的错误日志。

在此输入图像描述

在此输入图像描述

有什么建议如何解决吗?

编辑:更新了 nginx conf 文件

upstream backend{
        server localhost:3000;
    }
    server {
        listen       80;
        listen  443 ssl;
        server_name  localhost;
        ssl_certificate localhost.cert;
        ssl_certificate_key localhost.key;

        location / {
            root   html;
            index  index.html index.htm;
            proxy_pass http://backend;
            proxy_set_header X-Forwarded-Proto https;
            proxy_set_header X-Forwarded-Ssl on;
            proxy_set_header origin 'http://localhost:3000';
            proxy_set_header X-Forwarded-Port 443;
        }
Run Code Online (Sandbox Code Playgroud)

Mil*_*red 5

上述解决方案对我不起作用,但促使我调查代理变量。

我可以使用以下代码片段使其工作:

server {
  listen 443;
  location / {
    proxy_set_header Host $http_host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Host $http_host;
    proxy_set_header X-Forwarded-Port $server_port;
    proxy_set_header X-Forwarded-Server $host;
    proxy_set_header X-Forwarded-Ssl on;
    proxy_set_header X-Forwarded-Proto https;
    proxy_set_header Origin https://$http_host;
    proxy_redirect off;
    proxy_pass http://web:3000;
  }
  ...
}

Run Code Online (Sandbox Code Playgroud)

重要的是: - 使用$http_host而不是$host. 如果非默认端口号,$http_host还包含端口号。-除了 - 设置之外,在标头$http_host中使用设置端口号X-Forwarded-HostHostOrigin

特别是,使用不正确的标头设置 origin 可以让我在 Rails 中出现这样的错误,并且可以更轻松地调试它:

web_1 | W, [2020-05-04T13:30:33.381473 #1] WARN -- : [cc52d343-5826-4900-b0d8-477714cf9dc4] HTTP Origin header (https://localhost:443) didn't match request.base_url (https://localhost)