Devise中的InvalidAuthenticityToken :: SessionsController#destroy(已经注销后退出)

我正在使用Devise 3.2.0进行身份validation,并在执行以下操作时发现问题:

  • 标签1:登录应用
  • 选项卡2:转到应用程序中的任何页面
  • 选项卡2: 退出 (成功)
  • 选项卡1: 退出 (失败 – 请参阅下面的例外情况)

提出例外:

ActionController :: Devise中的InvalidAuthenticityToken :: SessionsController#destroy

在开发日志中,我看到:

无法validationCSRF令牌的真实性

堆栈跟踪的前三行是:

 ActionController::InvalidAuthenticityToken (ActionController::InvalidAuthenticityToken): actionpack (4.0.0) lib/action_controller/metal/request_forgery_protection.rb:163:in `handle_unverified_request' actionpack (4.0.0) lib/action_controller/metal/request_forgery_protection.rb:170:in `handle_unverified_request' devise (3.2.0) lib/devise/controllers/helpers.rb:198:in `handle_unverified_request' 

如何确保连续退出不会引发exception?

这是最新发生的事情,

当您最初从选项卡2注销时,与已登录用户关联的会话和authenticity_token已被销毁。 当您尝试从选项卡1注销时,Devise再次尝试使用在选项卡2上销毁的authenticity_token来销毁会话。

因此,您会收到错误ActionController::InvalidAuthenticityToken因为设计无法使用给定的authenticity_token

每次登录只能获得一个唯一的会话,如果它被破坏,你将无法再次销毁。

编辑

Devise不提供此行为。 如果您希望实现此类行为,则必须覆盖SessionsController。

app/controllers/users目录中创建sessions_controller.rb文件

 class Users::SessionsController < Devise::SessionsController prepend_before_filter :verify_user, only: [:destroy] private ## This method intercepts SessionsController#destroy action ## If a signed in user tries to sign out, it allows the user to sign out ## If a signed out user tries to sign out again, it redirects them to sign in page def verify_user ## redirect to appropriate path redirect_to new_user_session_path, notice: 'You have already signed out. Please sign in again.' and return unless user_signed_in? end end 

更新routes.rb

 devise_for :users, :controllers => { :sessions => "users/sessions" } 

解决这个问题的一个简单方法也可以是通过GET而不是DELETE进行注销。 在devise.rb中,您只需更改为:

 # The default HTTP method used to sign out a resource. Default is :delete. config.sign_out_via = :get 

您可以更改validationcsrf令牌的策略。

在rails 3中,validation失败时的默认策略是返回空会话。 在rails 4中,更改了application_controller中的策略以返回exception。

我解决了这个问题,改变了我的application_controller.rb

 class ApplicationController < ActionController::Base - protect_from_forgery, with: :exception + protect_from_forgery 

这样,使用默认策略。

这个错误在devise 3.3.0得到修复。

  • 请参阅3.3.0的更改日志
  • 请参阅pull请求#2968中的文件更改
  • 请注意config/locales/en.yml already_signed_out

Kirti是完全正确的。 我昨天遇到了这个问题但是使用了自定义身份validation解决方案。 如果这是您想要修复的问题,您可以弄清楚如何覆盖Devise的注销操作并skip_before_filter :verify_authenticity_token操作添加skip_before_filter :verify_authenticity_token

如果您仍然遇到此问题,就像我在Rails 5devise 4.4.1所做的那样,在app / controllers / application_controller.rb中更改

 protect_from_forgery with: :exception 

 protect_from_forgery with: :null_session 

希望能帮助到你。