简体   繁体   English

Rails 5 Devise:在sign_in失败时返回JSON

[英]Rails 5 Devise: Return JSON On sign_in Failure

Everything I seem to find on this issue is out of date and/or doesn't work. 我似乎在此问题上发现的所有内容都已过时和/或不起作用。

GOAL: When a user tries to sign in via JSON from a mobile application and the username or password is wrong, I would like Rails to return JSON data so the errors can be displayed on the app. 目标:当用户尝试通过移动应用程序通过JSON登录并且用户名或密码错误时,我希望Rails返回JSON数据,以便可以在应用程序上显示错误。

So far I have done the following: 到目前为止,我已经执行了以下操作:

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

This works well on success, but I'm not sure what to do when it fails. 这对成功很有效,但是我不确定失败时该怎么办。 Right now it returns an undefined method error: 现在,它返回一个未定义的方法错误:

undefined method `users_url' for #<Users::SessionsController:0x0000000195fa28>

You should take a look at this SO question that will point you in the right direction. 您应该看看这个SO问题 ,它将为您指明正确的方向。

Basically you need to handle the login failure. 基本上,您需要处理登录失败。 You could do this: 您可以这样做:

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

This handles JSON requests. 这处理JSON请求。 I hope this helps! 我希望这有帮助!

Figured it out. 弄清楚了。 CustomFailure never seemed to work, no matter how many things I tried. 无论我尝试了多少次,CustomFailure似乎都无法正常工作。 I was able to do this within the SessionsController via handle_failed_login: 我能够通过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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM