Расширение Session SessionController для аутентификации с использованием JSON - программирование
Подтвердить что ты не робот

Расширение 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'}}"
4b9b3361

Ответ 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.

Ответ 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

для ваших контроллеров.