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 5
和devise 4.4.1
所做的那样,在app / controllers / application_controller.rb中更改
protect_from_forgery with: :exception
至
protect_from_forgery with: :null_session
希望能帮助到你。