皆さん、WebとMobileの認証、どのようになってるんだろうなぁとよく思う今日この頃。DeviseとMobileの共存について調べたのでメモ。もっといい方法あったら教えて欲しいです。
Precondition
下記のようにして、UserというModelがdeviseを用いて作られている前提です。
rails generate devise User
あと、こちらを参考にしてます。
さて
全体の流れとしては
- Mobile用TokenカラムをUserテーブルに追加
- Mobile用Tokenを制御するControllerの作成
では
まず、Mobile用Tokenカラムを作成します。db/migrate/
のなかに適当なmigrateファイルを作成。僕の場合は20120418141059_add_devise_columns_to_user.rb
としました。中身はこんな感じ
class AddDeviseColumnsToUser < ActiveRecord::Migration
def self.up
change_table :users do |t|
t.token_authenticatable
end
end
def self.down
t.remove :authentication_token
end
end
そうそう、忘れぬうちに/app/model/user.rb
のbefore_filter
に:token_authenticatable
を追加しておく。
んで、rake db:migrate
を実行。
次にTokenを制御するControllerを作成します。
rails g controller api/v1/tokens
そしたら、config/route.rb
を編集。
namespace :api do
namespace :v1 do
resources :tokens,:only => [:create, :destroy]
end
end
はい、それではControllerの中身を書きます。下記の通り
class Api::V1::TokensController < ApplicationController
skip_before_filter :verify_authenticity_token
respond_to :json
def create
email = params[:email]
password = params[:password]
if request.format != :json
render :status=>406, :json=>{:message=>"The request must be json"}
return
end
if email.nil? or password.nil?
render :status=>400, :json=>{:message=>"The request must contain the user email and password."}
return
end
@user=User.find_by_email(email.downcase)
if @user.nil?
logger.info("User #{email} failed signin, user cannot be found.")
render :status=>401, :json=>{:message=>"Invalid email or passoword."}
return
end
@user.ensure_authentication_token
@user.save!
if not @user.valid_password?(password)
logger.info("User #{email} failed signin, password \"#{password}\" is invalid")
render :status=>401, :json=>{:message=>"Invalid email or passoword."}
else
render :status=>200, :json=>{:token=>@user.authentication_token}
end
end
def destroy
@user=User.find_by_authentication_token(params[:id])
if @user.nil?
logger.info("Token not found.")
render :status=>404, :json=>{:message=>"Invalid token."}
else
@user.reset_authentication_token!
render :status=>200, :json=>{:token=>params[:id]}
end
end
end
これで実装は終了!あとはアクセス!
http://localhost:3000/api/v1/tokens.jsonにPOSTでアクセス!Chromeのエクステンション「Simple REST Client」等でテストすると便利です。忘れていけないのがHeaderに
Content-type : application/x-www-form-urlencoded
を加えること。引数は
email=wirte_email_address_here&passowrd=write_passowrd_here
な感じになります。
Reference