使用Rails&Devise为移动设备建立一个简单的API登陆服务

使用Rails&Devise为移动设备建立一个简单的API登陆服务

使用的工具与源代码

Devise (https://github.com/plataformatec/devise)

Rails 4  (https://github.com/rails/rails)

Ruby-china 源代码 (https://github.com/ruby-china/ruby-china)

流程

利用API进行登陆,获取授权代码信息,使用授权代码信息与需要进行验证的API进行交互

配置Devise

增加authentication_token字段

假如应用已经初始化过了devise的user表,那么就需要额外利用rails生成一个新的数据迁移脚本

#rails g migration addAuthTokenToUser
class AddAuthTokenToUser < ActiveRecord::Migration
  def change
      change_table :users do |t|
          t.string :authentication_token
      end
      add_index  :users, :authentication_token, :unique => true
  end
end

编辑models/user.rb,增加相应的devise功能 :token_authenticatable

devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :trackable, :validatable,:token_authenticatable

建立控制器与路由

我们需要建立一个名为Token的控制器作为登陆/获取授权代码的入口

则先配置相应的路由,在config/routes.rb文件中增加以下代码

#config/routes.rb  
namespace :api do
    namespace :v1  do
      resources :tokens,:only => [:create, :destroy]
      resources :products
    end
 end

 然后新建相应的tokens_controller.rb文件,首先先写一个登陆登陆的方法

#controllers/api/v1/tokens_controller.rb
class Api::V1::TokensController  < ApplicationController

    skip_before_filter :verify_authenticity_token
    respond_to :json
    
    def create      
      email = params[:email]
      password = params[:password]
       
       if email.nil? or password.nil?
         render :status=>400,:json=>{:message=>"Password&Username cannot be blank"}
       return
       end

       @user=User.find_by_email(email.downcase)
        
      @user=User.find_by_email(email.downcase)
 
      if @user.nil?
         render :status=>401, :json=>{:message=>"Invalid email or passoword."}
        return
      end

       if not @user.valid_password?(password)
         render :status=>401, :json=>{:message=>"Invalid email or password."}
       else
         render :status=>200, :json=> {:token=>@user.authentication_token}
       end
    end

end

这样相当于建立一个api路径-localhost:3000/api/v1/tokens.json,顺便说明跳过的这个前置验证器

skip_before_filter :verify_authenticity_token

 因为rails默认会为所有Post的form增加一个提交表单用的验证代码,防止站外提交post方法。(《企业应用架构》一书里好似关于这种设计的具体说明)。但是通过手机提交post方法无法获取这段验证代码,所以api部分全部需要忽略这个内建的验证期。

测试

使用curl测试是不是正常工作

curl -XPOST -d ''  localhost:3000/api/v1/tokens.json

 因为没有输入用户名和密码应该返回一个我们设置的错误信息,{"message":"The request must contain the user email and password."}

如果输入正确的用和用户用户名如

curl -XPOST -d  "[email protected]&password=123456"  localhost:3000/api/v1/tokens.json

  则会收到一个正确的应答,并且获取相应用户的authentication_token栏位的值,{"token":"aiSf8jGqyPACcY3Myjxj"}。

不使用Devise的验证方法

阅读了Devise的文档,不知道是不是我会错意了,好似如果使用devise内置的auth_token方案,则web部分也会受到波及,需要使用authenticate_user!方法的地方都会额外验证auth_token,还需要修改devise.rb增加配置。

这里使用ruby-china一段很简单的验证方法,

def current_user
    token = params[:auth_token] 
    @current_user ||= User.where(:authentication_token => token).first
  end

  def authenticate!
     render :status=>400,
            :json=>{:message=>"Need login."} unless current_user
  end

 这里相当于重新实现了一个API专用的current_user 和 authenticate_user! 方法。相应的只需要在将来需要进行登陆验证的API中都加入auth_token=xxx的参数即可。

这里额外写一段需要炎验证的Controller代码进行演示:

class Api::V1::ListController.rb < ApplicationController
  before_filter :authenticate!   #验证token
  
  respond_to :json 

  def index
    @lists=List.all.limit(10)
     render :status=>200, :json=> @lists
  end

end

 如果使用curl 进行测试,则额外的需要在get请求中写明auth_token的参数值,例如 

localhost:3000/api/v1/lists.json?auth_token=xxx

结束语

这段代码只是演示如果利用Rails与Devise快速的建立一套需要验证的API体系。

相关推荐