我正在使用Devise 3.2.0
进行身份验证,并在执行以下操作时发现问题:
提出异常:
ActionDetroller :: 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'
如何确保连续退出不会引发异常?
答案 0 :(得分:10)
以下是发生的事情,
当您最初从标签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" }
答案 1 :(得分:5)
这个问题的简单解决方案也可以允许通过GET而不是DELETE进行注销。在devise.rb中,您只需更改为:
# The default HTTP method used to sign out a resource. Default is :delete.
config.sign_out_via = :get
答案 2 :(得分:2)
将其粘贴在布局中: <%= csrf_meta_tags%>
答案 3 :(得分:1)
您可以更改验证csrf令牌的策略。
在rails 3中,验证失败时的默认策略是返回空会话。在rails 4中,更改了application_controller中的策略以返回异常。
我解决了这个问题,改变了我的 application_controller.rb
class ApplicationController < ActionController::Base
- protect_from_forgery, with: :exception
+ protect_from_forgery
这样,使用默认策略。
答案 4 :(得分:1)
此错误已在devise 3.3.0
修复。
already_signed_out
config/locales/en.yml
答案 5 :(得分:0)
Kirti完全正确。我昨天遇到了这个问题,但使用自定义身份验证解决方案。如果这确实是您想解决的问题,您可以了解如何覆盖Devise的退出操作并为该操作添加skip_before_filter :verify_authenticity_token
。
答案 6 :(得分:0)
如果您仍然遇到此问题,就像我在Rails 5
和devise 4.4.1
中所做的那样,在app / controllers / application_controller.rb中更改
protect_from_forgery with: :exception
到
protect_from_forgery with: :null_session
希望它有所帮助。