2013-07-29 22 views
2

这里是我的SessionsController:设计与JSON请求不工作登录身份验证失败时

class SessionsController < Devise::SessionsController 
    respond_to :json 

    def create 
    resource = warden.authenticate!(scope: resource_name, recall: "#{controller_path}#failure") 
    sign_in(resource_name, resource) 
    return render json: { success: true, path: root_path } 
    end 

    def failure 
    return render json: { success: false, errors: ['Login information is incorrect, please try again'] } 
    end 
end 

用户#active_for_authentication

def active_for_authentication? 
    super && active_flag == 1 && has_active_subscription? 
    end 

服务器响应:

Started POST "https://stackoverflow.com/users/sign_in" for 127.0.0.1 at 2013-07-29 15:11:39 -0500 
Processing by SessionsController#create as JSON 
    Parameters: {"utf8"=>"✓", "authenticity_token"=>"ozQ00tw9rRWExCmlIyIZR07ovnTLab5w0W44cLAKwA4=", "user"=>{"email"=>"[email protected]", "password"=>"[FILTERED]"}, "commit"=>"Sign In"} 
    User Load (1.0ms) SELECT "users".* FROM "users" WHERE "users"."type" IN ('User', 'Athlete', 'Coach') AND "users"."email" = '[email protected]' LIMIT 1 
    (0.6ms) BEGIN 
    AccountType Load (0.5ms) SELECT "account_types".* FROM "account_types" WHERE "account_types"."id" = $1 LIMIT 1 [["id", 3]] 
    AccountType Load (0.7ms) SELECT "account_types".* FROM "account_types" WHERE "account_types"."id" = 3 LIMIT 1 
    (0.5ms) COMMIT 
Completed 401 Unauthorized in 338ms 


Started GET "https://stackoverflow.com/users/sign_in.json" for 127.0.0.1 at 2013-07-29 15:11:40 -0500 
Processing by SessionsController#new as JSON 
Completed 200 OK in 13ms (Views: 1.6ms | ActiveRecord: 0.0ms) 

出于某种原因,浏览器中的请求包含一个包含电子邮件和密码作为属性的用户对象。失败的json不会因任何原因渲染。不知道我做错了

编辑

#Devise  
config.http_authenticatable_on_xhr = false 

的CoffeeScript:

$(document).on 'ajax:success', '.user_modal_form', (e, data) -> 
     context = $(this) 
     if data.success 
     $('input[type="submit"]', context).hide() 
     $('.spinner', context).show() 

     if data.path? 
      window.location.href = data.path 
     else 
      location.reload() 
     else 
     e.preventDefault() 
     if data.errors? 
      $('.error-messages', context).html(data.errors).parent().show() 
     else 
      $('button', context).show() 
      $('.spinner', context).hide() 
      $('.alert', context).show() 

     false 

回答

0

我不知道为什么你得到了登录凭据的对象,但设计处理错误通过它的FailureApp - 确保你覆盖它,所以当401被触发时,warden会回顾自定义操作。

这是在你的色器件初始化完成后,config/initializers/devise.rb

一下添加到初始化并重新启动服务器:

config.http_authenticatable_on_xhr = false 
config.navigational_formats = [:html, :json] 
+0

调整我的代码上面,以匹配我在我的应用程序中,我仍然得到同样奇怪的问题的用户对象被返回在JSON响应 – dennismonsewicz

4

这里是我的伤口与去那些谁可能在稍后绊倒在路上...

#config/initializers/devise.rb: 
config.http_authenticatable_on_xhr = true 
config.navigational_formats = [:"*/*", "*/*", :html, :json] 

SessionsController

class SessionsController < Devise::SessionsController 
    respond_to :json 

    def create 
    resource = warden.authenticate!(scope: resource_name, recall: "#{controller_path}#failure") 
    sign_in(resource_name, resource) 
    return render json: { success: true, path: root_path } 
    end 

    def failure 
    return render json: { success: false, errors: ['Login information is incorrect, please try again'] } 
    end 
end 

路线

# I have implemented STI (Single Table Inheritance) into my app, therefore I skip sessions and passwords for the :user scope  
devise_for :users, skip: :registrations, controllers: { sessions: "sessions", passwords: "passwords" } 

的usermodel

def active_for_authentication? 
    super && active_flag == 1 && has_active_subscription? 
    end 

    def inactive_message 
    "Your subscription has been canceled or has expired." 
    end 

的CoffeeScript:

$(document).on 'ajax:success', '.user_modal_form', (e, data) -> 
     context = $(this) 
     log data 
     if data.success 
     $('input[type="submit"]', context).hide() 
     $('.spinner', context).show() 

     if data.path? 
      window.location.href = data.path 
     else 
      location.reload() 
     else 
     e.preventDefault() 
     if data.errors? 
      $('.error-messages', context).html(data.errors).parent().show() 
     else 
      $('button', context).show() 
      $('.spinner', context).hide() 
      $('.alert', context).show() 

     false 
    .on 'ajax:error', '.user_modal_form', (event, xhr, ajaxOptions, thrownError) -> 
     json = $.parseJSON(xhr.responseText) 
     $('.error-messages', $(this)).html(json.error).parent().show() 
1

下面的代码添加到您的会话控制器创建控制器上的failure方法自定义您的JSON回应:

def auth_options 
    super.merge(recall: "#{controller_path}#failure") 
end 

def failure 
    render json: {error: "Login failed"}, status: :unauthorized 
end 

显然recall的默认选项是#{controller_path}#new,我认为这可能对html有意义。如果您想限制为只有json请求,则可以在auth_options中使用respond_to。