讓 Rails 支援 API 登入

Step 1 : 安裝 Devise

  • rails g devise:install
  • rails g devise user
  • rake db:migrate

Step 2 : 新增認證 Token 到 user

  • rails g migration AddAuthTokenToUsers
  1. class AddAuthTokenToUsers < ActiveRecord::Migration[5.0]
  2. def change
  3. add_column :users, :authentication_token, :string
  4. add_index :users, :authentication_token
  5. end
  6. end
  • rake db:migrate

Step 3 : 修改 user model

  1. class User < ApplicationRecord
  2. # Include default devise modules. Others available are:
  3. # :confirmable, :lockable, :timeoutable and :omniauthable
  4. devise :database_authenticatable, :registerable,
  5. :recoverable, :rememberable, :trackable, :validatable
  6. before_save do
  7. if authentication_token.blank?
  8. self.authentication_token = generate_authentication_token
  9. end
  10. end
  11. def generate_authentication_token
  12. loop do
  13. token = Devise.friendly_token
  14. break token unless User.where(authentication_token: token).first
  15. end
  16. end
  17. end

Step 4 : 修改 application_controller 關掉 CSRF

  1. class ApplicationController < ActionController::Base
  2. protect_from_forgery with: :null_session
  3. before_action :authenticate_user_from_token!
  4. def authenticate_user_from_token!
  5. authenticate_with_http_token do |token, options|
  6. user = User.find_by(email: options.fetch(:email))
  7. if user && Devise.secure_compare(user.authentication_token, token)
  8. sign_in user, store: false
  9. end
  10. end
  11. end
  12. end

Step 5 : 使用客製 sessions_controller

  • rails g controller sessions
  1. class SessionsController < Devise::SessionsController
  2. respond_to :json
  3. def create
  4. super do |user|
  5. data = {
  6. token: user.authentication_token,
  7. email: user.email
  8. }
  9. render(json: data, status: 201) && return
  10. end
  11. end
  12. end

Step 6 : 修改 config/routes.rb

  1. Rails.application.routes.draw do
  2. devise_for :users, controllers: { sessions: "sessions" }
  3. # .....
  4. end