Ruby-扩展Devise SessionsController以使用JSON进行身份验证

我正在尝试为iPhone应用程序构建Rails API。 Devise对于通过Web界面登录的工作效果很好,但是我需要能够使用REST API创建和销毁会话,并且我想使用JSON而不是必须在会话控制器上执行POST以及解析HTML并处理 重定向。

我以为我可以做这样的事情:

class Api::V1::SessionsController < Devise::SessionsController  
  def create
    super
  end  
  def destroy
    super
  end  
end

并在config / routes.rb中添加:

namespace :api do
  namespace :v1 do
    resources :sessions, :only => [:create, :destroy]
  end
end

耙路线显示路线已正确设置:

   api_v1_sessions POST   /api/v1/sessions(.:format)     {:action=>"create", :controller=>"api/v1/sessions"}
    api_v1_session DELETE /api/v1/sessions/:id(.:format) {:action=>"destroy", :controller=>"api/v1/sessions"}

当我发布到/ user / sessions时,一切正常。 我得到一些HTML和302。

现在,如果我发布到/ api / v1 / sessions,则会得到:

未知动作 AbstractController :: ActionNotFound

curl -v -H 'Content-Type: application/json' -H 'Accept: application/json'   -X POST http://localhost:3000/api/v1/sessions   -d "{'user' : { 'login' : 'test', 'password' : 'foobar'}}"
7个解决方案
41 votes

这才是最终成功的方法。

class Api::V1::SessionsController < Devise::SessionsController  
  def create  
    respond_to do |format|  
      format.html { super }  
      format.json {  
        warden.authenticate!(:scope => resource_name, :recall => "#{controller_path}#new")  
        render :status => 200, :json => { :error => "Success" }  
      }  
    end  
  end  
  def destroy  
    super  
  end  
end  

还要更改routes.rb,记住顺序很重要。

devise_for :users, :controllers => { :sessions => "api/v1/sessions" }
devise_scope :user do
  namespace :api do
    namespace :v1 do
      resources :sessions, :only => [:create, :destroy]
    end
  end
end

resources :users
Akshay Kumar answered 2020-06-17T12:13:09Z
10 votes

我最终使用了@akshay的答案和@ mm2001的答案。

class Api::SessionsController < Devise::SessionsController
  def create
    warden.authenticate!(:scope => resource_name, :recall => "#{controller_path}#failure")
    render :json => {:success => true}
  end

  def destroy
    Devise.sign_out_all_scopes ? sign_out : sign_out(resource_name)
    render :json => {}
  end

  def failure
    render :json => {:success => false, :errors => ["Login Failed"]}
  end
end

...并且在设计初始化程序中,我必须执行此操作才能获取#create方法以使用我的2926924652524024080处理程序

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

这是与Devise 1.5.1和Rails 3.1一起使用的。

declan answered 2020-06-17T12:13:38Z
8 votes

这里的最新答案:[http://jessehowarth.com/devise]有更多详细信息(每个使用Devise 1.3来认证JSON登录请求)

mm2001 answered 2020-06-17T12:13:58Z
5 votes

我通过创建一个用于分配身份验证令牌的小型服务解决了该问题。 我写了一篇关于它的博客文章:[http://matteomelani.wordpress.com/2011/10/17/authentication-for-mobile-devices/。]您还可以在此处获取代码:[https://github.com/matteomelani/Auth-Token-Service-Prototype。]

Matteo Melani answered 2020-06-17T12:14:18Z
1 votes

从rdev的devise的#devise_scope中:

设置要在控制器中使用的设计范围。 如果您有自定义路线,您需要调用此方法(也别名为:as)以指定定位到哪个控制器。

as :user do
  get "sign_in", :to => "devise/sessions#new"
end

注意,您不能有两个范围映射到同一URL。 记住,如果您尝试在不指定范围的情况下访问设备控制器,它将引发ActionNotFound错误。

看来您需要将其包装在#as块中:

as :user do
  namespace :api do
    namespace :v1 do
      resources :sessions, :only => [:create, :destroy]
    end
  end
end
Michael Nutt answered 2020-06-17T12:14:52Z
1 votes

创建/销毁会话的另一种解决方案是使用Devise的token_authenticatable模块,然后更新API中的其他函数,以使它们将令牌作为必需参数。 可以说这是一种更具ReSTful的设计,因为它保留了无状态性(即,任何地方都没有会话状态)。 当然,此建议适用于您的JSON API,但我不建议您将其用于HTML UI(浏览器的URL栏中的长标记字符串并不是很漂亮)。

请参阅此处的示例。

Ricky Robinson answered 2020-06-17T12:15:17Z
0 votes

不确定是否应使用导航格式,API并不是真的...

根据此博客文章添加

respond_to :html, :json

给您的控制器。

aceofspades answered 2020-06-17T12:15:46Z
translate from https://stackoverflow.com:/questions/4857855/extending-devise-sessionscontroller-to-authenticate-using-json