ActionController::InvalidAuthenticityToken 使用 NGINX 和 Rails 登录

ActionController::InvalidAuthenticityToken at login using NGINX and Rails

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

这是我当前的 nginx 配置文件

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;
        }

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

的错误日志

有什么解决方法的建议吗?

编辑:更新了 nginx 配置文件

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;
        }

尝试通过添加更多 headers X-Forwarded-Ssl onX-Forwarded-Port 443X-Forwarded-Host "your hostname"X-Forwarded-Proto https 来修复。

CSRF tokens are checked by ActionController (compares the request.base_url with the origin header)

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

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

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;
  }
  ...
}

重要的是: - 使用 $http_host 而不是 $host。在非默认端口号的情况下,$http_host 也包含端口号。 - 除了 Host 之外,还使用 ​​X-Forwarded-Host header 中的 $http_host 设置端口号 - 设置 Origin

特别是,用不正确的 header 设置 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)