Расширение Session SessionController для аутентификации с использованием JSON
Я пытаюсь создать API-интерфейс rails для приложения iphone. Devise отлично работает для входа через веб-интерфейс, но мне нужно иметь возможность создавать и уничтожать сеансы с использованием 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"}
Когда я отправляю POST на /user/sessions, все работает нормально. Я получаю HTML и 302.
Теперь, если я получаю POST в/api/v1/сеансы, я получаю:
Неизвестное действие 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'}}"
Ответы
Ответ 1
Это то, что наконец сработало.
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
Также измените route.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
Ответ 2
В итоге я использовал комбинацию ответов @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 использовал обработчик :recall
# config/initializers/devise.rb
config.navigational_formats = [:"*/*", "*/*", :html, :json]
Это с помощью Devise 1.5.1 и Rails 3.1.
Ответ 3
Недавний ответ здесь: http://jessehowarth.com/devise содержит более подробную информацию (за Использование Devise 1.3 для аутентификации запросов на вход в JSON)
Ответ 4
Я решил проблему, создав небольшую службу, которая распределяет токены аутентификации. Я написал сообщение в блоге об этом: http://matteomelani.wordpress.com/2011/10/17/authentication-for-mobile-devices/.
Вы также можете получить код здесь: https://github.com/matteomelani/Auth-Token-Service-Prototype.
Ответ 5
Из rdoc для разработки #devise_scope:
Устанавливает область разработки, которая будет использоваться в контроллере. Если у вас есть пользовательские маршруты,
вы должны вызвать этот метод (также псевдоним как: как), чтобы указать
на какой контроллер он нацелен.
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
Ответ 6
Альтернативным решением для создания/уничтожения сеансов является использование модуля Devise token_authenticatable
, а затем обновление других функций в вашем API, чтобы они приняли маркер в качестве обязательного параметра. Это, возможно, более переработанный дизайн, поскольку он сохраняет безгражданство (т.е. Нет ни одного состояния сеанса нигде). Разумеется, этот совет подходит для вашего JSON API, но я бы не рекомендовал его для вашего HTML UI (длинные строки токенов в вашем браузере URL-панели не очень привлекательны).
См. здесь для примера.
Ответ 7
Нельзя использовать навигационные форматы, API на самом деле не так...
За это сообщение в блоге просто добавьте
respond_to :html, :json
для ваших контроллеров.