2014-12-17 3 views
0

Я пишу backend приложения в Rails. Когда я работаю над бэкэнд, мне нужно предоставить разработчику frontend API REST для начала создания интерфейса. В конце концов, интерфейс и бэкэнд будут находиться вместе в одном приложении, но пока они разделены.Devise Json Authentication

В настоящее время я включил совместное использование ресурсов Перекрестной происхождении в моем приложении, добавив следующее ApplicationController:

config.action_dispatch.default_headers.merge!({ 
                'Access-Control-Allow-Origin' => '*', 
                'Access-Control-Request-Method' => '*' 
               }); 

В настоящем время, я также выключил CSRF токенов, добавив следующее application.rb:

skip_before_filter :verify_authenticity_token 

Я использую Devise для аутентификации пользователей. Для того, чтобы разработать работу с запросами JSON, я сделал следующее:

В devise.rb

config.navigational_formats = ['*/*', :html, :json] 

В routes.rb

devise_for :users, :controllers => {:omniauth_callbacks => "omniauth_callbacks", :sessions => 'sessions', :registrations => 'registrations' } 

Мои SessionsController

class SessionsController < Devise::SessionsController 
    #todo had to do following to support logging in through ajax. need to add logic to send back error response when login fails. 
    #todo see http://stackoverflow.com/questions/5973327/using-devise-1-3-to-authenticate-json-login-requests/8402035#8402035 and 
    #todo https://web.archive.org/web/20130928040249/http://jessehowarth.com/devise 
    #todo see http://stackoverflow.com/questions/11277300/devise-failure-authentication-via-json-sends-back-html-instead-of-json 
    def create 
    respond_to do |format| 
     format.html { super } 
     format.json { 
     resource = warden.authenticate!(:scope => resource_name, :recall => "#{controller_path}#failure") 
     sign_in(resource_name, resource) 
     return render :json => {:success => true, :user => resource} 
     } 
    end 
    end 

    def destroy 
    respond_to do |format| 
     format.html { super } 
     format.json { 
     Devise.sign_out_all_scopes ? sign_out : sign_out(resource_name) 
     render :json => {} 
     } 
    end 
    end 

    def failure 
    render :json => {:success => false, :errors => ["Login Failed"]}, :status => 422 
    end 
end 

У меня есть расширенный RegistrationsController DEViSE в а также указано в routes.rb, но я не размещаю его содержание здесь, так как я не думаю, что это относится к этому вопросу.

С выше настройки я могу отправить AJAX запрос на «/ пользователей/sign_in» с пользователем [электронной почты] и пользователей [пароль] параметров и которые пользователь подписан в ответ выглядит примерно так:.

{ 
success: true 
user: { 
    authentication_token: "SNa2kPqkm5ENsZMx7yEi" 
    created_at: "2014-12-16T02:40:39.179Z" 
    email: "[email protected]" 
    id: 99999 
    name: null 
    provider: null 
    uid: null 
    updated_at: "2014-12-17T02:29:31.537Z" 
} 
} 

Теперь как использовать authentic_token, который я получил в ответе sign_in, чтобы отправлять запросы другим действиям контроллера, требующим аутентификации пользователя? Нужно ли устанавливать этот токен в заголовке запроса? Я не могу найти информацию о том, как использовать этот токен. Пожалуйста помоги.

ответ

0

Как представляется, как описано в данном документе, ответ заключается в том, что вы отправляете электронную почту suer и authetication_token с каждым запросом на бэкэнд. Вы можете отправить его в заголовок запроса или просто как параметры. Вы просто изменяете метод, который проверяет электронную почту и токен и знаки в пользователе в ApplicationController соответственно. Это мой ApplicationController (я теперь отправки электронной почты и жетона в качестве параметров в запросе):

class ApplicationController < ActionController::Base 
    # Prevent CSRF attacks by raising an exception. 
    # For APIs, you may want to use :null_session instead. 
    protect_from_forgery with: :exception 
    #todo remove this once ui is integrated. following turns off the csrf token: 
    skip_before_filter :verify_authenticity_token 

    #todo begin code to support authentication using token 
    # This is our new function that comes before Devise's one 
    before_filter :authenticate_user_from_token! 
    # This is Devise's authentication 
    before_filter :authenticate_user! 

    private 

    def authenticate_user_from_token! 
    user_email = params[:user_email].presence 
    user  = user_email && User.find_by_email(user_email) 

    # Notice how we use Devise.secure_compare to compare the token 
    # in the database with the token given in the params, mitigating 
    # timing attacks. 
    if user && Devise.secure_compare(user.authentication_token, params[:user_token]) 
     sign_in user, store: false 
    end 
    end 
    #todo end code to support authentication using token 
end 

Я забыл упомянуть в моем посте, что я уже добавил миграции, чтобы добавить столбец authentication_token в модели пользователя. Кроме того, я должен был добавить следующее в модели User (как описано в gist), так что токен аутентификации создается каждый раз, когда пользователь создается/обновляется:

#todo begin code to support ajax authentication of users 
    #todo see https://gist.github.com/josevalim/fb706b1e933ef01e4fb6 
    # You likely have this before callback set up for the token. 
    before_save :ensure_authentication_token 

    def ensure_authentication_token 
    if authentication_token.blank? 
     self.authentication_token = generate_authentication_token 
    end 
    end 

    private 

    def generate_authentication_token 
    loop do 
     token = Devise.friendly_token 
     break token unless User.where(authentication_token: token).first 
    end 
    end 
    #todo end code to support ajax authentication of users 
Смежные вопросы