我正在使用Devise 3.2.0
进行身份验证,并在执行以下操作时发现问题:
标签1:登录在对应用程序
选项卡2:转到应用程序中的任何页面
选项卡2:退出(成功)
选项卡1:退出(失败 - 请参阅下面的例外)
提出例外:
ActionController :: Devise中的InvalidAuthenticityToken :: SessionsController#destroy
在开发日志中我看到:
无法验证CSRF令牌的真实性
堆栈跟踪的前三行是:
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'
如何确保连续退出不会引发异常?
这是最新发生的事情,
当您最初从选项卡2注销时,与已登录用户关联的会话和authenticity_token已被销毁.当您尝试从选项卡1注销时,Devise再次尝试使用在选项卡2上销毁的authenticity_token来销毁会话.
因此,您会收到错误,ActionController::InvalidAuthenticityToken
因为设计无法使用给定的身份验证authenticity_token
.
每次登录只能获得一个唯一的会话,如果它被破坏,你将无法再次销毁.
编辑
Devise不提供此行为.如果您希望实现此类行为,则必须覆盖SessionsController.
sessions_controller.rb
在app/controllers/users
目录中创建一个文件
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