Rails/Devise:如何在Sessions控制器中判断用户登录是否成功
方案1:重写SessionsController的create动作(最贴合需求,实现成本最低)
你不需要用Warden钩子或者FailureApp就能实现和普通模型#create/#update完全一致的错误判断逻辑,直接重写Devise登录的创建动作即可:
- 首先配置路由指定自定义的会话控制器
在config/routes.rb中添加:
devise_for :users, controllers: { sessions: "users/sessions" }
- 编写自定义会话控制器的逻辑
在app/controllers/users/sessions_controller.rb中写入:
class Users::SessionsController < Devise::SessionsController def create # 尝试走正常登录流程 self.resource = warden.authenticate!(auth_options) set_flash_message!(:notice, :signed_in) sign_in(resource_name, resource) yield resource if block_given? respond_with resource, location: after_sign_in_path_for(resource) rescue Warden::InvalidAuthenticationError # 登录失败分支,和普通模型报错逻辑完全对齐 self.resource = resource_class.new(sign_in_params) resource.errors.add(:base, t("devise.failure.invalid")) # 直接渲染登录页模板,状态码用422和普通表单报错保持一致 render :new, status: :unprocessable_entity end end
- 视图层直接复用你熟悉的错误判断写法
在登录页的ERB模板中,你可以直接用和@article报错完全一样的逻辑:
<% if resource.errors.any? %> <div id="error_explanation"> <h2> <%= pluralize(resource.errors.count, "error") %> prohibited this user from logging in: </h2> <ul> <% resource.errors.full_messages.each do |msg| %> <li><%= msg %></li> <% end %> </ul> </div> <% end %>
方案2:自定义Devise::FailureApp(适合全局处理所有认证失败场景)
你问到的Devise::FailureApp没有强制要求返回JSON,完全可以渲染ERB模板、partial,和普通Rails控制器的渲染逻辑没有任何区别,实现方式如下:
- 编写自定义FailureApp
创建app/lib/custom_failure_app.rb:
class CustomFailureApp < Devise::FailureApp def respond if http_auth? http_auth elsif request.format.html? # HTML请求直接渲染登录页模板,携带错误信息 flash.now[:alert] = i18n_message render "devise/sessions/new", status: :unprocessable_entity else # 非HTML请求(比如JSON)走默认逻辑 super end end end
- 配置Devise使用自定义FailureApp
在config/initializers/devise.rb中添加配置:
config.warden do |manager| manager.failure_app = CustomFailureApp end
内容的提问来源于stack exchange,提问作者von spotz
相关产品推荐
相关产品推荐

