设计用户sign_in为CSRF令牌真实性令牌提供身份validation错误

我正在使用带有rails devise (最新版本 – 3.2.0)(最新版本 – 4.0.1)

我正在进行简单的身份validation(没有ajax或api)并且获得CSRF真实性令牌的错误。 检查下面的POST请求

 started POST "/users/sign_in" for 127.0.0.1 at 2013-11-08 19:48:49 +0530 Processing by Devise::SessionsController#create as HTML Parameters: {"utf8"=>"✓", "authenticity_token"=>"SJnGhXXUXjncnPhCdg3muV2GYCA8CX2LVFV78pqddD4=", "user"=> {"email"=>"a@a.com", "password"=>"[FILTERED]", "remember_me"=>"0"}, "commit"=>"Sign in"} Can't verify CSRF token authenticity User Load (0.4ms) SELECT "users".* FROM "users" WHERE "users"."email" = 'a@a.com' LIMIT 1 (0.1ms) begin transaction SQL (0.4ms) UPDATE "users" SET "last_sign_in_at" = ?, "current_sign_in_at" = ?, "sign_in_count" = ?, "updated_at" = ? WHERE "users"."id" = 2 [["last_sign_in_at", Fri, 08 Nov 2013 14:13:56 UTC +00:00], ["current_sign_in_at", Fri, 08 Nov 2013 14:18:49 UTC +00:00], ["sign_in_count", 3], ["updated_at", Fri, 08 Nov 2013 14:18:49 UTC +00:00]] (143.6ms) commit transaction Redirected to http://localhost:3000/ Completed 302 Found in 239ms (ActiveRecord: 144.5ms | Search: 0.0ms) 

根URL指向home#new ,就像

 class HomeController < ApplicationController before_action :authenticate_user! def index end end 

Sign_in页面生成的html视图如下:

  • 元标签

       
  • 形成

     


身份validation请求甚至会更新last_sign_in_atsign_in_count值,但是当我尝试访问控制器中的current_user ,它将为nil

据我说,它实际上并没有登录user 。 但接下来的问题是“它为什么要在user表中更新last_sign_in_at / sign_in_count值?”

当CSRF令牌不正确时,Rails将不会读取或对会话进行任何更新。 它仍将执行控制器指定的任何其他操作,这解释了为什么您看到数据库更新但最终未登录。

我注意到日志和页面中的authenticity_token不匹配。 我意识到这可能是因为您捕获了不同的请求,但是您应该检查页面上的那个请求是否与日志中的请求相匹配。 我还假设您在视图中使用了正确的标记,每次都会生成不同的authenticity_token,而不仅仅是对HTML输入进行硬编码。

您是否看到与设计无关的表格存在同样的问题? 如果没有,作为解决方法,您可以使用控制器中的以下代码免除CSRF检查中的操作:

 protect_from_forgery except: :sign_in 

对你的登录行动进行CSRF攻击的可能性对我来说似乎很遥远(<-pun)。

此外,如果它只是设计,那么我建议你提交一个问题, 你已经完成了 。

设计gem没有问题。 我删除了’rails-api’gem,我的应用程序开始工作了。

在应用程序控制器上添加它(这适用于Rails 5)

 protect_from_forgery unless: -> { request.format.json? } 

将其添加到Devise SessionController

 skip_before_action :verify_authenticity_token, only: [:create] 

尝试curl

 curl -X POST -v -H 'Content-Type: application/json' http://0.0.0.0:3000/users/sign_in -d '{"user" : {"email": "name@mail.com", "password": "secret" }}' 

我在视图中删除了“remote:true”选项修复了同样的问题:将form_for(model,remote:true)更改为form_for(model)