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'}}"
これが最終的に機能したものです。
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の回答と@ 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。
ここでの最近の回答: http://jessehowarth.com/devise にはさらに詳細があります( JSONログイン要求を認証するためにDevise 1.3を使用 )
認証トークンを配布する小さなサービスを作成することで問題を解決しました。それについてのブログ記事を書きました: http://matteomelani.wordpress.com/2011/10/17/authentication-for-mobile-devices/ 。ここでコードを取得することもできます: https://github.com/matteomelani/Auth-Token-Service-Prototype 。
セッションを作成/破棄する別の解決策は、Deviseのtoken_authenticatable
モジュールを使用し、APIの他の関数を更新して、トークンを必須パラメーターとして使用するようにします。これは、ステートレス性を保持するため(つまり、セッションステートがどこにも存在しないため)、おそらくよりReSTfulなデザインです。もちろん、このアドバイスはJSON APIにも当てはまりますが、HTML UIにも同じことはお勧めしません(ブラウザーのURLバーにある長いトークン文字列は見栄えがよくありません)。
例については here を参照してください。
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
ナビゲーション形式を使用する必要があるかどうかはわかりませんが、APIは実際にはそうではありません...
このあたり ブログ投稿 追加するだけ
respond_to :html, :json
コントローラーに。