使用轨道和设计。在下面的代码中,我检查用户是否已经使用omniauth登录(使用
email
和 provider
字段进行检查)。如果是,那么我想通过默认消息来失败。虽然以下代码有效,但我手动调用 devise.failure.invalid
消息,我不喜欢这样做。
我想调用 Devise 中的一些现有方法,以便它可以模拟失败的登录,这样我就不必重新定义东西。
class Users::SessionsController < Devise::SessionsController
before_action :check_omniauth_presence, only: [:create]
private
def check_omniauth_presence
resource = resource_class.where(email: params[resource_name][:email]).where.not(provider: nil)
if resource.present?
auth_keys = resource_class.authentication_keys.first.to_s
flash[:alert] = t("devise.failure.invalid", authentication_keys: auth_keys)
redirect_to new_session_path(resource_name)
end
end
end
在这里你可以看到我重新定义了
authentication_keys
,手动调用翻译。我尝试了set_flash_message
(但仍然是手动)和warden.authenticate!(nil)
,但没有成功。
您可以利用 Devise 在幕后使用的 Warden 内置故障机制。
warden
对象有一个 fail!
方法,该方法采用符号来表示失败原因,并且在调用时将停止请求周期并直接进入失败应用程序(即您的设计失败应用程序)。
Devise 的故障应用程序将使用此符号为您设置适当的闪烁消息。以下是您如何重构代码以利用它:
class Users::SessionsController < Devise::SessionsController
prepend_before_action :check_omniauth_presence, only: [:create]
private
def check_omniauth_presence
resource = resource_class.where(email: params[resource_name][:email]).where.not(provider: nil)
if resource.present?
# Fail the authentication using Warden's built-in mechanism
warden.custom_failure!
throw(:warden, reason: :invalid)
end
end
end
以下是我们所做工作的详细说明:
prepend_before_action
:我们使用 before_action
来代替 prepend_before_action
,以确保我们的方法在堆栈中的任何其他方法之前被调用。
warden.custom_failure!
:告诉 Warden 存在自定义失败,因此不应继续使用默认身份验证策略。
throw(:warden, reason: :invalid)
:这是对Warden失败机制的实际调用。它抛出一个符号 (:warden
),Warden 中间件会捕获该符号。 reason: :invalid
部分通知失败应用程序身份验证失败的原因,然后使用它来设置适当的闪存消息。
使用这种方法,您不再需要手动设置闪现消息或处理重定向,因为 Devise 故障应用程序将为您处理这些事情。