gpt4 book ai didi

html - 为什么 Rails 给我 "Can' t verify CSRF token authenticity”错误?

转载 作者:太空狗 更新时间:2023-10-29 14:20:30 25 4
gpt4 key购买 nike

我在 Rails 生产中收到“无法验证 CSRF token 真实性”。我的问题是:

  1. 为什么要这样做?
  2. 我该如何解决?

这是我的 Heroku 日志(一些值已匿名):

2016-02-13T01:18:54.118956+00:00 heroku[router]: at=info method=POST path="/login" host=[MYURL] request_id=[ID STRING] fwd="FWDIP" dyno=web.1 connect=0ms service=6ms status=422 bytes=1783  
2016-02-13T01:18:54.116581+00:00 app[web.1]: Started POST "/login" for [IPADDRESS] at 2016-02-13 01:18:54 +0000
2016-02-13T01:18:54.119372+00:00 app[web.1]: Completed 422 Unprocessable Entity in 1ms
2016-02-13T01:18:54.118587+00:00 app[web.1]: Processing by SessionsController#create as HTML
2016-02-13T01:18:54.118637+00:00 app[web.1]: Parameters: {"utf8"=>"✓", "authenticity_token"=>"[BIGLONGRANDOMTOKENSTRING]", "session"=>{"email"=>"[FRIENDSEMAILADDRESS]", "password"=>"[FILTERED]", "remember_me"=>"0"}, "commit"=>"Log in"}
2016-02-13T01:18:54.119082+00:00 app[web.1]: Can't verify CSRF token authenticity
2016-02-13T01:18:54.120565+00:00 app[web.1]:
2016-02-13T01:18:54.120567+00:00 app[web.1]: ActionController::InvalidAuthenticityToken (ActionController::InvalidAuthenticityToken):
2016-02-13T01:18:54.120569+00:00 app[web.1]: vendor/bundle/ruby/2.2.0/gems/actionpack-4.2.0/lib/action_controller/metal/request_forgery_protection.rb:181:in `handle_unverified_request'
.
.
.etc

我所知道的唯一表现是当我的 friend 试图在他的 iPhone 5 上使用 Safari 登录时。他的用户帐户是大约 6 个月前创建的。我 99% 确定他当时用手机可以正常访问该网站。从那以后他就没有登录过,我也不知道我对登录/授权码做了任何更改。昨天我让他在大约 6 个月内第一次访问我的网站,现在他遇到了 CSRF 错误。

此问题不会发生在任何其他用户帐户(据我所知)或任何其他设备上。事实上,从他的旧款 iPhone 4 登录他的帐户就可以了。

我有相当多的开发经验,但对网络开发和 Rails 的一切都是全新的。

这是我所拥有的:

class ApplicationController < ActionController::Base
# Prevent CSRF attacks by raising an exception.
# For APIs, you may want to use :null_session instead.
protect_from_forgery with: :exception
include SessionsHelper
end

应用布局:

<!DOCTYPE html>
<html>
<head>
<title><%= full_title(yield(:title)) %></title>
<meta name="viewport" content="width=device-width,initial-scale=1">
<%= stylesheet_link_tag 'application', media: 'all' %>
<%= javascript_include_tag 'application' %>
<%= csrf_meta_tags %>
<%= render 'layouts/shim' %>
</head>
<body>
<%= render 'layouts/header' %>
<div class="container">
<% flash.each do |message_type, message| %>
<div class="alert alert-<%= message_type %>"><%= message %></div>
<% end %>
<%= yield %>
<%= render 'layouts/footer' %>
<%= debug(params) if Rails.env.development? %>
</div>
</body>
</html>

我的 secret 文件如下所示:

# Do not keep production secrets in the repository,
# instead read values from the environment.
production:
secret_key_base: <%= ENV["SECRET_KEY_BASE"] %>

我在 Heroku 上有一个用于 secret_key_base 的生产环境变量。

def log_in(user)
session[:user_id] = user.id
end

def remember(user)
user.remember
cookies.permanent.signed[:user_id] = user.id
cookies.permanent[:remember_token] = user.remember_token
end

这是我所做的:
我按照 Michael Hartl's Rails Tutorial 中的所有内容开始开发我的应用程序直到第 10 章为止/一直到第 10 章。最相关的是第 8 章。具体来说,我的应用程序使用所有安全/cookie/用户身份验证内容,与 tut 中完全一样。我没有在我的应用程序中做任何花哨的事情……没有 AJAX 或类似的东西。我什至猛拉了turbolinks。

我的项目跨越了过去 18 个月,所以我不能 100% 肯定我是从哪个版本开始的。我知道它是 4.1.X,可能是 4.1.6。我也不确定我升级的日期,但在某些时候对我目前正在运行的进行了升级; 4.2.0。

我几乎阅读了我在网上找到的所有关于 CSRF + Rails 问题的帖子。似乎对于我读过的几乎所有内容,原因和解决方案都与 AJAX 或 Devise 有关,但两者都不适用于我。 iFrame 问题是网络上的另一个常见来源,我都没有使用它。

我使用了我的应用程序的密码重置功能但无济于事。我尝试将 protect_from_forgery 更改为 with: :reset_session。唯一的变化是不再显示 Rails 异常页面。但它不会让他转到任何需要身份验证的页面。它只是让他回到根目录,因为我的 route 有这一行:

get '*path' => redirect('/')

我不想清除他的 cookie/缓存等,因为我有许多其他现有用户帐户,我不想手动修复它们。

经常建议的解决方案是关闭安全性的一些变体,出于显而易见的原因我不想这样做。

其他一些我已经更改但还没有机会测试的东西(因为我不能轻松访问我 friend 的 iPhone):

我更改了 session_store.rb 中的应用商店名称:

Rails.application.config.session_store :cookie_store, key: '[NEWNAME]'

运行以下命令:
heroku 运行 rake assets:clean
heroku 运行 rake assets:precompile

我即将开始深潜here ,尤其是第 3 节。

感谢阅读/考虑。任何提示/想法/建议/指针将不胜感激!

最佳答案

结果 this gentleman遇到了与我完全相同的问题,并且能够创建一个对我有用的复制案例。如果我没理解错的话,Safari 会缓存页面,但会破坏 session 。这导致 authenticity_token 值在我的 rails 参数中看起来合法,但 protect_from_forgery 在验证 token 时失败,因为 session 已被破坏。

解决方案有两个:关闭缓存和处理 CSRF 异常。即使您关闭缓存,您仍然需要处理异常,因为某些浏览器(例如 Safari)不遵守无缓存设置。在这种情况下会出现 CSRF 问题,因此也需要处理该问题。

我的解决方法是通过清除我所有的 cookie 和 session 数据来处理 CSRF 异常,闪烁一条“oops”消息并将它们重定向到登录页面。重定向将拉取一个新的身份验证 token ,该 token 将在执行登录后进行验证。这个想法来自here :

It is common to use persistent cookies to store user information, with cookies.permanent for example. In this case, the cookies will not be cleared and the out of the box CSRF protection will not be effective. If you are using a different cookie store than the session for this information, you must handle what to do with it yourself:

rescue_from ActionController::InvalidAuthenticityToken do |exception|
sign_out_user # Example method that will destroy the user cookies
end

The above method can be placed in the ApplicationController and will be called when a CSRF token is not present or is incorrect on a non-GET request.

cookies.permanent 正是我使用的。所以我像这样实现了上面的技巧:

class ApplicationController < ActionController::Base  
include SessionsHelper
protect_from_forgery with: :exception
before_filter :set_cache_headers
rescue_from ActionController::InvalidAuthenticityToken do |exception|
cookies.delete(:user_id)
cookies.delete(:remember_token)
session.delete(:user_id)
@current_user = nil
flash[:danger] = "Oops, you got logged out. If this keeps happening please contact us. Thank you!"
redirect_to login_path
end

def set_cache_headers
response.headers["Cache-Control"] = "no-cache, no-store, max-age=0, must-revalidate"
response.headers["Pragma"] = "no-cache"
response.headers["Expires"] = "Fri, 01 Jan 1990 00:00:00 GMT"
end
end

顺便说一句,在实现修复并验证它在开发中工作后,我 friend 的手机仍然无法登录,尽管行为有所不同。经过调查,我发现他在 iPhone 5 Safari 设置中“阻止了所有 cookie”。这导致了其他奇怪的行为,使得很难找出是哪个问题导致了什么。当我意识到我无法使用他的手机登录任何在线帐户(例如雅虎邮箱等)时,就收到了提示。进入他的 Safari 设置并允许 cookie 解决了问题,现在他的手机(以及我所知道的其他任何地方)一切正常。

关于html - 为什么 Rails 给我 "Can' t verify CSRF token authenticity”错误?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35417479/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com