Rails 5 设计:登录失败时返回 JSON

问题描述 投票:0回答:3

我在这个问题上找到的所有内容似乎都已过时和/或不起作用。

目标:当用户尝试从移动应用程序通过 JSON 登录并且用户名或密码错误时,我希望 Rails 返回 JSON 数据,以便可以在应用程序上显示错误。

到目前为止我已经做了以下事情:

class Users::SessionsController < Devise::SessionsController
  # before_action :configure_sign_in_params, only: [:create]
  skip_before_action :verify_authenticity_token
  respond_to :json

  # POST /resource/sign_in
  def create
    self.resource = warden.authenticate!(auth_options)
    set_flash_message(:notice, :signed_in) if is_flashing_format?
    sign_in(resource_name, resource)
    yield resource if block_given?
    respond_with resource, :location => after_sign_in_path_for(resource) do |format|
      format.json {render :json => resource } # this code will get executed for json request
    end
  end
end

这在成功时效果很好,但我不知道失败时该怎么办。现在它返回一个未定义的方法错误:

undefined method `users_url' for #<Users::SessionsController:0x0000000195fa28>
ruby-on-rails json devise ruby-on-rails-5
3个回答
0
投票

您应该看看这个问题,它将为您指明正确的方向。

基本上你需要处理登录失败的情况。你可以这样做:

class CustomFailure < Devise::FailureApp
  def respond
    if http_auth?
      http_auth
    elsif request.content_type == "application/json"
      self.status = 401
      self.content_type = "application/json"
      self.response_body = {success: false, error: "Unauthorized"}.to_json
    else
      redirect
    end
  end
end

这处理 JSON 请求。我希望这有帮助!


0
投票

想通了。无论我尝试了多少方法,CustomFailure 似乎都不起作用。我可以通过handle_failed_login在SessionsController中执行此操作:

class Users::SessionsController < Devise::SessionsController
  # before_action :configure_sign_in_params, only: [:create]
  after_filter :handle_failed_login, :only => :new
  skip_before_action :verify_authenticity_token
  respond_to :json

  # POST /resource/sign_in
  def create
    self.resource = warden.authenticate!(auth_options)
    set_flash_message(:notice, :signed_in) if is_flashing_format?
    sign_in(resource_name, resource)
    yield resource if block_given?
    respond_with resource, :location => after_sign_in_path_for(resource) do |format|
      format.json {render :json => resource } # this code will get executed for json request
    end
  end

  private
  def handle_failed_login
    if failed_login?
      render json: { success: false, errors: ["Login Credentials Failed"] }, status: 401
    end
  end 

  def failed_login?
    (options = env["warden.options"]) && options[:action] == "unauthenticated"
  end 
end

0
投票

我按照 the devise JWT github 上的指南遇到了同样的问题。我无法让自定义

FailureApp
接管并响应。

经过一番调试,失败的应用程序已注册,但

http_auth_body
内部的关键行是
return super unless request_format == :json

我需要将

defaults: { format: :json }
添加到我的设计路由配置中,以便请求格式为 JSON 而不是 HTML。解决此问题后,自定义故障应用程序将接管并使用 JSON 正确响应。

# config/routes.rb
Rails.application.routes.draw do
  devise_for :users, defaults: { format: :json } #FIX
end

# devise/failure_app.rb
class FailureApp < Devise::FailureApp
  def http_auth_body
    return super unless request_format == :json

    {
      sucess: false,
      message: i18n_message
    }.to_json
  end
end

# config/initializers/devise.rb
Devise.setup do |config|
  config.warden do |manager|
    manager.failure_app = FailureApp
  end
end

© www.soinside.com 2019 - 2024. All rights reserved.