web-dev-qa-db-ja.com

JSONを使用して認証するためのDevise SessionsControllerの拡張

IPhoneアプリ用のRails APIを構築しようとしています。DeviseはWebインターフェースを介したログインに対して正常に動作しますが、REST API。セッションコントローラーでPOSTを実行し、HTMLを解析してリダイレクトを処理する代わりに、JSONを使用します。

私はこのようなことができると思った:

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"}

I POST to/user/sessionsがすべて正常に動作します。HTMLと302を受け取ります。

I POST to/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'}}"
47
Akshay Kumar

これが最終的に機能したものです。

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
41
Akshay Kumar

最終的には、@ 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

...そして、devise初期化子では、#createメソッドで:recallハンドラー

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

これはDevise 1.5.1およびRails 3.1。

10
declan

ここでの最近の回答: http://jessehowarth.com/devise にはさらに詳細があります( JSONログイン要求を認証するためにDevise 1.3を使用

8
mm2001

認証トークンを配布する小さなサービスを作成することで問題を解決しました。それについてのブログ記事を書きました: http://matteomelani.wordpress.com/2011/10/17/authentication-for-mobile-devices/ 。ここでコードを取得することもできます: https://github.com/matteomelani/Auth-Token-Service-Prototype

5
Matteo Melani

セッションを作成/破棄する別の解決策は、Deviseのtoken_authenticatableモジュールを使用し、APIの他の関数を更新して、トークンを必須パラメーターとして使用するようにします。これは、ステートレス性を保持するため(つまり、セッションステートがどこにも存在しないため)、おそらくよりReSTfulなデザインです。もちろん、このアドバイスはJSON APIにも当てはまりますが、HTML UIにも同じことはお勧めしません(ブラウザーのURLバーにある長いトークン文字列は見栄えがよくありません)。

例については here を参照してください。

1
Ricky Robinson

Deviseの#devise_scopeのrdocから:

コントローラーで使用されるdeviseスコープを設定します。カスタムルートがある場合、このコントローラー(別名:as)を呼び出して、ターゲットにするコントローラーを指定する必要があります。

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

2つのスコープを同じURLにマッピングすることはできません。また、スコープを指定せずにdeviseコントローラーにアクセスしようとすると、ActionNotFoundエラーが発生することを忘れないでください。

#asブロックでラップする必要があるようです:

as :user do
  namespace :api do
    namespace :v1 do
      resources :sessions, :only => [:create, :destroy]
    end
  end
end
1
Michael Nutt

ナビゲーション形式を使用する必要があるかどうかはわかりませんが、APIは実際にはそうではありません...

このあたり ブログ投稿 追加するだけ

respond_to :html, :json

コントローラーに。

0
aceofspades