Extension de Devise SessionsController pour l’authentification à l’aide de JSON

J’essaie de construire une API de rails pour une application iphone. Devise fonctionne bien pour les connexions via l’interface Web, mais je dois pouvoir créer et détruire des sessions à l’aide de l’API REST et utiliser JSON plutôt que de devoir effectuer un POST sur le contrôleur de sessions et parsingr le HTML et gérer un réorienter.

Je pensais pouvoir faire quelque chose comme ça:

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

et dans config / routes.rb j’ai ajouté:

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

routes rake montre que les routes sont configurées correctement:

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

Lorsque je poste vers / utilisateur / sessions, tout fonctionne bien. Je reçois du HTML et un 302.

Maintenant, si je lance vers / api / v1 / sessions, je reçois:

Action inconnue 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'}}" 

C’est ce qui a finalement fonctionné.

 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 

Changez également routes.rb, rappelez-vous que la commande est importante.

 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 

J’ai fini par utiliser une combinaison de la réponse de @ akshay et de la réponse de @ 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 

… et dans l’initialiseur, je devais le faire pour obtenir la méthode #create pour utiliser my :recall gestionnaire de :recall

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

Ceci est avec Devise 1.5.1 et Rails 3.1.

Une réponse récente ici: http://jessehowarth.com/devise a plus de détails (à l’ aide de Devise 1.3 pour authentifier les demandes de connexion JSON )

J’ai résolu le problème en créant un petit service qui dissortingbue des jetons d’authentification. J’ai écrit un article de blog à ce sujet: http://matteomelani.wordpress.com/2011/10/17/authentication-for-mobile-devices/ . Vous pouvez également obtenir le code ici: https://github.com/matteomelani/Auth-Token-Service-Prototype .

Du rdoc pour le dispositif #devise_scope:

Définit la scope du dispositif à utiliser dans le contrôleur. Si vous avez des routes personnalisées, vous devez appeler cette méthode (également appelée alias as) afin de spécifier à quel contrôleur elle est ciblée.

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

Notez que vous ne pouvez pas avoir deux étendues de mappage sur la même URL. Et rappelez-vous, si vous essayez d’accéder à un contrôleur de périphérique sans spécifier d’étendue, cela provoquera une erreur ActionNotFound.

Il semble que vous ayez besoin de l’envelopper dans un bloc #as:

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

Une solution alternative à la création / destruction de sessions consiste à utiliser le module token_authenticatable de Devise, puis à mettre à jour les autres fonctions de votre API afin qu’elles prennent le jeton comme paramètre obligatoire. Il s’agit sans doute d’une conception plus efficace, car elle conserve l’apasortingdie (c’est-à-dire qu’il n’ya aucun état de session). Bien sûr, ce conseil est valable pour votre API JSON, mais je ne recommanderais pas la même chose pour votre interface utilisateur HTML (les longues chaînes de jetons dans la barre d’URL de votre navigateur ne sont pas très belles).

Voir ici pour un exemple.

Pas sûr que les formats de navigation devraient être utilisés, une API n’est pas vraiment ça …

Per ce blog ajoute juste

 respond_to :html, :json 

à vos contrôleurs.