Расширение Devise SessionsController для аутентификации с использованием JSON - PullRequest
47 голосов
/ 01 февраля 2011

Я пытаюсь создать API-интерфейс для приложения iphone. Devise прекрасно работает для входа в систему через веб-интерфейс, но мне нужно иметь возможность создавать и уничтожать сеансы с помощью REST API, и я хочу использовать JSON вместо необходимости выполнять POST на контроллере сессий и разбирать HTML и иметь дело с перенаправление.

Я думал, что смогу сделать что-то вроде этого:

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

и в config / rout.rb я добавил:

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

Rake Routes показывает, что маршруты настроены правильно:

   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 / session, все работает нормально. Я получаю немного HTML и 302.

Теперь, если я помещаю POST в / api / v1 / session, я получаю:

Неизвестное действие 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'}}"

Ответы [ 7 ]

40 голосов
/ 12 февраля 2011

Это то, что, наконец, сработало.

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  

Также измените маршруты. 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
10 голосов
/ 06 февраля 2012

Я использовал комбинацию ответа @ 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.

8 голосов
/ 07 июня 2011

Недавний ответ здесь: http://jessehowarth.com/devise содержит некоторые подробности (за Использование Devise 1.3 для аутентификации запросов входа в систему JSON )

5 голосов
/ 27 октября 2011

Я решил проблему, создав небольшой сервис, выдающий токены аутентификации.Я написал в блоге об этом: http://matteomelani.wordpress.com/2011/10/17/authentication-for-mobile-devices/. Вы также можете получить код здесь: https://github.com/matteomelani/Auth-Token-Service-Prototype.

1 голос
/ 14 июня 2011

Альтернативным решением для создания / уничтожения сеансов является использование модуля token_authenticatable Devise, а затем обновление других функций в вашем API, чтобы они принимали токен в качестве обязательного параметра.Это, возможно, более ReSTful дизайн, так как он сохраняет безгражданство (то есть, нигде нет состояния сеанса).Конечно, этот совет применим для вашего JSON API, но я бы не рекомендовал то же самое для вашего HTML-интерфейса (длинные строки токенов в строке URL вашего браузера не очень привлекательны). для примера.

1 голос
/ 01 февраля 2011

Из 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
0 голосов
/ 09 июня 2014

Не обязательно использовать навигационные форматы, API не совсем такой ...

За это сообщение в блоге просто добавьте

respond_to :html, :json

вваши контроллеры.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...