我在这个问题上找到的所有内容似乎都已过时和/或不起作用。
目标:当用户尝试从移动应用程序通过 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>
您应该看看这个问题,它将为您指明正确的方向。
基本上你需要处理登录失败的情况。你可以这样做:
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 请求。我希望这有帮助!
想通了。无论我尝试了多少方法,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
我按照 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