为什么 Rails 给出“无法验证 CSRF 令牌真实性”错误?

2024-03-02

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

  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  

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

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

我有相当多的开发经验,但对 Web 开发和 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>

我的秘密文件如下所示:

# 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 的 Rails 教程 https://www.railstutorial.org/book/frontmatter直到第 10 章为止。最相关的是第 8 章。具体来说,我的应用程序使用所有安全/cookie/用户身份验证内容,与图特中完全相同。我在我的应用程序中没有做任何花哨的事情......没有 AJAX 或类似的东西。我什至猛拉涡轮链接。

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

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

我使用了应用程序的密码重置功能,但没有效果。我尝试将 protected_from_forgery 更改为 with: :reset_session。唯一改变的是 Rails 异常页面不再显示。但它不会让他进入任何需要身份验证的页面。这只是让他回到根目录,因为我的路线中有这一行:

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

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

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

我已经更改了其他一些内容,但还没有机会测试(因为我无法轻松访问我朋友的 iPhone):

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

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

运行以下命令:
heroku 运行 rake 资产:clean
heroku 运行 rake 资产:预编译

我即将开始深潜here http://guides.rubyonrails.org/security.html,特别是第 3 节。

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


事实证明这位先生 https://github.com/rails/rails/issues/21948遇到了与我完全相同的问题,并且能够创建一个对我有用的重现案例。如果我理解正确的话,Safari 会缓存页面,但会破坏会话。这导致在我的 Rails 参数中,authenticity_token 值看起来合法,但在验证令牌时,protect_from_forgery 失败,因为会话已被破坏。

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

我的解决方法是通过杀死所有 cookie 和会话数据来处理 CSRF 异常,闪烁“oops”消息并将它们重定向到登录页面。重定向将拉下一个新的身份验证令牌,该令牌将在执行登录帖子时进行验证。这个想法来自here http://guides.rubyonrails.org/security.html#csrf-countermeasures:

使用持久性cookie来存储用户信息是很常见的,例如cookies.permanent。在这种情况下,cookie 将不会被清除,开箱即用的 CSRF 保护也不会生效。如果您使用与会话不同的 cookie 存储来存储此信息,则必须自行处理如何处理它:

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

上述方法可以放置在 ApplicationController 中,并且当 CSRF 令牌不存在或在非 GET 请求上不正确时将被调用。

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  

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

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

为什么 Rails 给出“无法验证 CSRF 令牌真实性”错误? 的相关文章

  • Rails 4 应用程序...在开发环境中,除非刷新页面,否则 javascript 不会触发

    所以我的第一个rails4应用程序遇到了一个奇怪的问题 除非我重新加载页面 否则我的页面javascript不会触发 对于我的 asset pipeline JS 和 content for JS 来说都是如此 在我的 assets jav
  • 如何在不关闭浏览器自动完成建议的情况下改进它们?

    这里有十个无数的线程 如何disable浏览器自动完成行为 例如如何禁用网络表单字段 输入标签上的浏览器自动完成功能 https stackoverflow com questions 2530 how do you disable bro
  • Bundle 说 gem 丢失了 - 但事实并非如此?

    背景 我正在维护contentRuby On Rails 站点 但我确实没有 Rails 的经验 当尝试运行 Rails 服务器时 rails s我明白了 在任何来源中均找不到 activesupport 3 2 0 Run bundle
  • 有没有办法编写屏幕阅读器会忽略的内容?

    我刚刚开发了一个需要视力正常和视障用户都可以访问的页面 内容的某些元素仅与视觉元素相关 因此根本不适用于使用屏幕阅读器的人 例如 链接在新窗口中打开视听演示文稿 但由于我无法控制的情况 窗口的大小被笨拙地调整 因此有一条消息说您应该调整窗口
  • Flexbox 的行之间可以有一条线吗?

    我有一个水平导航 它有点长 需要重新排列以适应狭窄的显示 我使用 flexbox 使其重排成多行 但行数较多时 导航项之间的划分就不那么明显了 我尝试在顶部给它们一个边框 它有点有效 但当然 边框仅在各个导航选项上可见 而不是在所有 Fle
  • python:API 令牌生成及其危险

    我正在按照 Flask Web Development 一书来实现基于令牌的身份验证 基本上 用户使用 HTTP 基本身份验证对其进行身份验证 并为其生成令牌 s Serializer app config SECRET KEY expir
  • 滚动时输入自动完成位置错误(chrome)

    我在输入文本的默认自动完成功能方面遇到了一些麻烦 滚动时它不会相应移动 我希望自动完成文本保留在输入的正下方 有办法做到这一点吗 我在 Chrome 浏览器版本 57 0 2987 133 中发生这种情况 fiddle https jsfi
  • 如何向我的网站添加 Google 搜索框?

    我正在尝试将 Google 搜索框添加到我自己的网站 我希望它搜索谷歌本身 而不是我的网站 我曾经有一些代码可以工作 但现在不再工作
  • 在 javascript、jQuery 或 css 中,如何让 div 或 iframe 展开以填充其余空间

    我有三个 iframe 我将顶部 iframe 设置为 50px 高度 将底部 iframe 设置为 50px 但我希望中间 iframe 扩展以填充其余空间 有没有一种技术可以用来对任何窗口屏幕尺寸执行此操作 谢谢 example
  • 如何在 font Awesome 图标链接下方添加添加文本?

    我正在尝试在我的 Blogger 模板中的 font awesome Icons 下添加一些文本 这是我想要实现的目标的图像 我想要实现的外观图片 https i stack imgur com BVYlh png 但到目前为止我已经做到了
  • html 表格单元格的条件格式

    是否有现成的解决方案可以对 HTML 表格进行条件格式设置 通过条件格式 我更感兴趣的是根据该列或其他列 在同一个表中 的值 数字 将不同的颜色作为单元格背景 类似于我们在 Excel 条件格式 gt 色阶 gt 红黄绿中的内容 我想在通过
  • 如何动态突出显示网页上的字符串?

    我想创建带有 url 的页面 例如 http xyzcorp schedules 2015Aug24 Aug28 Jim Hawkins http xyzcorp schedules 2015Aug24 Aug28 Billy Bones
  • 将文本大小调整为矩形 在 Canvas HTML5 中调整大小

    我是 Canvas 新手 我正在创建一个网站 以在调整矩形大小时增加文本 我尝试了很多 但没有任何效果 实际上 我希望如果我仅按其宽度调整矩形大小 向左拉伸 向右拉伸 则仅应增加文本宽度而不是字体大小 我已经完成了字体大小 但发现增加孤立文
  • 同页锚链接到部分 id 在 IE8 中不起作用

    我有一个带有导航的单页 HTML5 网站 可以将用户引导至该部分 在除 IE8 之外的所有浏览器中都可以正常工作 IE8 不执行任何操作 我所拥有的虚拟版本 a href about About a a href work Work a a
  • 循环遍历元素并逐步为每个元素应用 CSS 规则

    我有一个网格布局 每个网格布局中都有不同数量的元素 我想动态添加内联grid column通过循环遍历 div 中存在的每个元素的 CSS 规则 ul 与一类 list 所以 HTML 代码的输出需要是 ul class list ul u
  • Rails Windows Vagrant 响应时间非常慢

    我在跑 Vagrant 1 7 1 Rails 4 1 4 Thin 1 6 1 Windows 7 每个静态文件的发送时间都超过一秒 在我的 PC 上加载一个页面可能需要大约 20 秒 而在同事的 Linux 机器上则只需瞬间 有一些帖子
  • 如何检测元素内容何时发生变化

    我正在寻找一种方法来监视元素内动态填充 无页面重新加载 内容 以便我可以将类添加到另一个元素 到目前为止我有这个 HTML div class message container div class messages error span
  • Jquery 在 DIV 中进行多重加载

    这是我的代码 right load textes html nicolas right load textes html antoine 问题是内容divantoine覆盖了右边div nicolas加载的内容div div right l
  • 将rails_admin 与rails_api 结合使用

    我最初将此发布为Rails api GitHub 上的问题 https github com sferik rails admin issues 2617 但由于不活跃 我现在将其发布在这里 我正在尝试使用rails admin使用 Rai
  • HTML 属性 bgcolor 已弃用:用什么代替?

    VStudio ASP NET 给出以下消息 Attribute bgcolor is considered outdated A newer construct is recommended 推荐的结构是什么 bgcolor是在一个 td

随机推荐

  • Apache http 基本身份验证?

    是否有一些简单的代码可以添加到 htaccess文件或我的虚拟主机文件来强制执行 http 基本身份验证 那这个呢 AuthUserFile my derectory htpasswd Require valid user AuthName
  • HTML CSS DIV 面板

    I want to make something like this 到目前为止我所做的 谁能告诉我如何实现这一目标 谢谢 提前 See jsFiddle http jsfiddle net SanaBukhari DAFW9 代码如下 H
  • 每个 Android 应用程序的网络流量监控

    我想知道我是否可以对每个 Android 应用程序进行网络流量监控 基本上看看哪个应用程序正在接收 发送多少数据 我知道有很多应用程序已经做到了这一点 但我想知道如何做到这一点 嗯 你当然可以 一个非常简单的方法是使用交通统计 http d
  • PostgreSQL 和 ActiveRecord 子选择竞争条件

    我在 ActiveRecord 和 PostgreSQL 中遇到竞争条件 我正在读取一个值 然后递增它并插入一条新记录 num Foo where bar id 42 maximum number Foo create bar id 42
  • jedi-vim 和 YouCompleteMe 冲突吗?

    YouCompleteMe YCM 和 jedi vim 是两个提供自动补全功能的 vim 插件 并且都在 Python 下使用 jedi 不过 两者兼得是件好事 因为 jedi vim 除了文档之外还提供了一些有用的功能 例如 转到定义
  • 访客模式中的泛型杀伤力过大

    我正在开发一个项目 将十年前编写的旧 java 1 2 代码转换为 java 7 该项目大量 过度 使用特定访问者 为了使事情在概念上简单 我们假设访问者是这样的 public interface RobotVisitor public O
  • Google Chrome 调试器跳过断点

    我目前正在尝试在 chrome 中调试 js 脚本 我在脚本中放置了一个断点 当我仅使用一个选项卡时 它会正确中断 但在第二个选项卡上 即使我在代码中看到断点 它也不会中断 查看源代码时是否使用了漂亮的打印选项 我注意到格式化的副本可能会不
  • 有非官方的 Flash .FLA 规范吗?

    是否有非官方规范解释如何对 Flash FLA 文件进行逆向工程 我对创建一个应用程序特别感兴趣 该应用程序可以通过编程方式 自动场景规划 Flash 文档 从其他文件中提取内容 将该内容排列到图层中 而无需打开 Flash IDE 然后动
  • 使用 IB 将分段控件添加到导航栏

    我目前正在创建一个UISegmentedControl以编程方式在视图控制器中viewDidLoad方法并将其分配给视图控制器的导航栏self navigationItem titleView 这很简单 但我也希望能够在 Interface
  • 与 pypi.org 的连接超时

    无法 pip 安装 3rd 方软件包 venv pip install django Collecting django Retrying Retry total 4 connect None read None redirect None
  • 使用 R Lubridate 提取会计年度

    我将创建几个日期 library lubridate x lt ymd c 2012 03 26 2012 05 04 2012 09 23 2012 12 31 我可以从中提取年份和季度x values quarter x with ye
  • 如何创建文件选择器以使用 REST API 将文件保存到 Google Drive?

    现在谷歌是不赞成 https developers google com drive android deprecationGoogle Drive Android API 我正在将代码迁移到 Drive REST API 我几乎已经完成了
  • 如何正确使用WriteConsoleOutputAttribute函数

    为什么下面的代码 const std string text str HANDLE stdout handle GetStdHandle STD OUTPUT HANDLE COORD coords 0 0 DWORD written 0
  • 如何强制子div的高度为父div高度的100%而不指定父div的高度?

    我有一个具有以下结构的网站 div div div div div div div div div div 导航位于左侧 内容 div 位于右侧 内容div的信息是通过PHP拉入的 所以每次都是不同的 如何垂直缩放导航 使其高度与内容 di
  • 如何仅显示多类别绘图条形图的类别刻度并旋转它们

    我希望不使用plotly graph objects 在多类别条形图中显示内部类别标签 此外 我希望旋转外部类别标签的标签 这是我的代码 import pandas as pd import plotly graph objects as
  • R 中多列的聚合和加权平均值

    问题基本上是这样的 R 中的聚合和加权平均值 https stackoverflow com questions 3367190 aggregate and weighted mean in r 但我希望它使用 data table 在几列
  • 如何在 laravel 或 php 中动态更改 php dotenv (.env) 变量?

    我想要这样的东西 env APP ENV setenv APP ENV testing env APP ENV Output staging testing 我找到一个答案如何在 Laravel 中动态更改 env 文件中的变量 https
  • Java 中的通用 Fluent Builder

    我知道也有过类似的问题 但我还没有看到我的问题的答案 我将用一些简化的代码来展示我想要的东西 假设我有一个复杂的对象 它的一些值是通用的 public static class SomeObject
  • Django 身份验证适用于 Chrome,但不适用于 Firefox

    我遇到了一个问题 Django 的登录在 Chrome 上工作正常 但在 Firefox 上却不行 当尝试在 Firefox 上登录网站的受限部分时 它只是一次又一次地循环回到登录页面 此外 日志上没有出现与此相关的错误消息 有趣的是 当服
  • 为什么 Rails 给出“无法验证 CSRF 令牌真实性”错误?

    我在 Rails 生产中收到 无法验证 CSRF 令牌真实性 的消息 我的问题是 它为什么要这样做 我该如何修复它 这是我的 Heroku 日志 一些值已匿名 2016 02 13T01 18 54 118956 00 00 heroku