旧行李 2014-12-17 02:38 采纳率: 25%
浏览 30

Devise Json身份验证

I am writing backend of an app in Rails. As I work on the backend, I need to give the frontend developer a REST API to start building the frontend. Eventually, the frontend and backend will reside together in a single app, but for now they are separate.

For time being I have enabled Cross-origin resource sharing in my app, by adding following to ApplicationController:

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

For now, I have also turned off CSRF tokens by adding following to application.rb:

skip_before_filter :verify_authenticity_token

I am using Devise for authenticating users. To make Devise work with JSON requests, I have done following:

In devise.rb

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

In routes.rb

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

My 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

I have a extended Devise's RegistrationsController as well as indicated in routes.rb, but am not posting its content here, as I don't think it is relevant to this question.

With the above setup I am able to send an ajax request to '/users/sign_in' with user[email] and user[password] parameters and have the user signed in. The response looks something like this:

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

Now how do I use the authentication_token I received in the sign_in response to send requests to other controller actions that require user to be authenticated? Do I need to set this token in a request header? I am not able to find information on how to use this token. Please help.

  • 写回答

1条回答 默认 最新

  • weixin_33711641 2014-12-17 04:03
    关注

    It seems following as described in the gist here, the answer is that you send the suer's email and authetication_token with every request to the backend. You may choose to send it in request header or simply as parameters. You simply modify the method that checks the email and token and signs in the user in ApplicationController accordingly. This is my ApplicationController (I am now sending the email and token as parameters in the request):

    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
    

    I forgot to mention in my post that I had already added the migration to add a authentication_token column to User model. Also, I had to add following in the User model (as described in the gist), so that an authentication token is generated each time a user is created/updated:

    #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
    
    评论

报告相同问题?

悬赏问题

  • ¥15 基于卷积神经网络的声纹识别
  • ¥15 Python中的request,如何使用ssr节点,通过代理requests网页。本人在泰国,需要用大陆ip才能玩网页游戏,合法合规。
  • ¥100 为什么这个恒流源电路不能恒流?
  • ¥15 有偿求跨组件数据流路径图
  • ¥15 写一个方法checkPerson,入参实体类Person,出参布尔值
  • ¥15 我想咨询一下路面纹理三维点云数据处理的一些问题,上传的坐标文件里是怎么对无序点进行编号的,以及xy坐标在处理的时候是进行整体模型分片处理的吗
  • ¥15 CSAPPattacklab
  • ¥15 一直显示正在等待HID—ISP
  • ¥15 Python turtle 画图
  • ¥15 stm32开发clion时遇到的编译问题