Rails 5 InvalidAuthenticityToken,但令牌存在
Rails 5 InvalidAuthenticityToken, but token is present
我正在 ActionController::InvalidAuthenticityToken 保存一个简单的资源..
存在 CSRF 元标记:
<meta name="csrf-token" content="Z4fDRsIqCp4cvpCw1Dp6kN7z0uPNF5otp611C80YhUg/oB+AcUy+dz2b5qKyoMMo48LdEvbF3dcBn2d0GqeR+g==" />
以及表单的标记字段:
<input type="hidden" name="authenticity_token" value="bIMZ5cndd/CTgOwjC3quOp02WlvWdDmhdNQCyKb920HIZz2Y8vvNDlTa7d4PKaJ5pUY6QkHKYCqiHikc2rFsyQ==" />
会话 ID 不会在请求之间持续存在,但我知道此行为是在发生 CSRF 错误时设计的。
表单代码:
<%= form_for document do |f| %>
<% if document.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(document.errors.count, "error") %> prohibited this document from being saved:</h2>
<ul>
<% document.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
控制器中的相关操作:
def new
@document = Document.new
end
def create
@document = Document.new(document_params)
respond_to do |format|
if @document.save
format.html { redirect_to @document, notice: 'Document was successfully created.' }
format.json { render :show, status: :created, location: @document }
else
format.html { render :new }
format.json { render json: @document.errors, status: :unprocessable_entity }
end
end
end
不知道如何解决这个问题,并且出于显而易见的原因,我不愿意关闭 CSRF 保护。
编辑:我正在通过一个 nginx 容器作为代理,也许我的配置不正确?这是配置:
upstream backend {
server service:3000;
}
server {
listen 80 default_server;
error_page 500 502 503 504 /500.html;
error_log /dev/stdout info;
access_log /dev/stdout;
location / {
proxy_pass http://backend;
}
}
对于其他 运行 在 nginx 代理后面的人来说,这是通过向 nginx 添加代理配置来解决的 here:
我错过了这些:
proxy_set_header X-Real_IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-NginX-Proxy true;
proxy_set_header Host $http_host;
proxy_set_header Upgrade $http_upgrade;
proxy_pass_header Set-Cookie;
我为这个问题苦苦挣扎了好几天,直到我终于在我的 nginx 设置中发现了这个缺失的行:
location @puma {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_redirect off;
proxy_set_header X-Forwarded-Proto https; # Needed to avoid 'WARNING: Can't verify CSRF token authenticity'
proxy_pass http://puma;
}
添加缺失的行 "proxy_set_header X-Forwarded-Proto https;" 后,我所有的 CSRF 令牌错误都退出了。
我正在 ActionController::InvalidAuthenticityToken 保存一个简单的资源..
存在 CSRF 元标记:
<meta name="csrf-token" content="Z4fDRsIqCp4cvpCw1Dp6kN7z0uPNF5otp611C80YhUg/oB+AcUy+dz2b5qKyoMMo48LdEvbF3dcBn2d0GqeR+g==" />
以及表单的标记字段:
<input type="hidden" name="authenticity_token" value="bIMZ5cndd/CTgOwjC3quOp02WlvWdDmhdNQCyKb920HIZz2Y8vvNDlTa7d4PKaJ5pUY6QkHKYCqiHikc2rFsyQ==" />
会话 ID 不会在请求之间持续存在,但我知道此行为是在发生 CSRF 错误时设计的。
表单代码:
<%= form_for document do |f| %>
<% if document.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(document.errors.count, "error") %> prohibited this document from being saved:</h2>
<ul>
<% document.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
控制器中的相关操作:
def new
@document = Document.new
end
def create
@document = Document.new(document_params)
respond_to do |format|
if @document.save
format.html { redirect_to @document, notice: 'Document was successfully created.' }
format.json { render :show, status: :created, location: @document }
else
format.html { render :new }
format.json { render json: @document.errors, status: :unprocessable_entity }
end
end
end
不知道如何解决这个问题,并且出于显而易见的原因,我不愿意关闭 CSRF 保护。
编辑:我正在通过一个 nginx 容器作为代理,也许我的配置不正确?这是配置:
upstream backend {
server service:3000;
}
server {
listen 80 default_server;
error_page 500 502 503 504 /500.html;
error_log /dev/stdout info;
access_log /dev/stdout;
location / {
proxy_pass http://backend;
}
}
对于其他 运行 在 nginx 代理后面的人来说,这是通过向 nginx 添加代理配置来解决的 here:
我错过了这些:
proxy_set_header X-Real_IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-NginX-Proxy true;
proxy_set_header Host $http_host;
proxy_set_header Upgrade $http_upgrade;
proxy_pass_header Set-Cookie;
我为这个问题苦苦挣扎了好几天,直到我终于在我的 nginx 设置中发现了这个缺失的行:
location @puma {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_redirect off;
proxy_set_header X-Forwarded-Proto https; # Needed to avoid 'WARNING: Can't verify CSRF token authenticity'
proxy_pass http://puma;
}
添加缺失的行 "proxy_set_header X-Forwarded-Proto https;" 后,我所有的 CSRF 令牌错误都退出了。