Devise Auth cho ứng dụng Rails sử dụng JSON Webservice
Bài đăng này đã không được cập nhật trong 8 năm
Chúng ta vẫn dùng thường dùng Rails
để tạo ra các ứng dụng web và khi muốn tạo một ứng dụng mobile-friendly
thì có hai con đường có thể chọn: hoặc là thiết kế một giao diện responsive hoặc là sẽ phát triển một ứng dụng cho các thiết bị di dộng. Để tạo ra một ứng dụng di động chúng ta phải tạo ra một giao diện để có thể kết nối tới server của ứng dụng Rails
, đó là khi Web services phát huy tác dụng. Trong bài viết này, chúng ta sẽ thử xây dựng một JSON Web service
cho ứng dụng Rails
Mục đích của chúng ta là xây dựng một API cho module xác thực người dùng sử dụng một gem rất quen thuộc là Devise
. Tuy nhiên vì lý do bảo mật mà trong build mới nhất Devise
đã bỏ đi tính năng token authentication.
Nhưng token authentication là gì? Có chức năng gì mà lại bị Devise
bỏ đi?
Hiểu một cách đơn giản, authentication_token giống như một thẻ nhân viên, khi bạn đi vào công ty (sign in) thì bạn cần phải có, đi đến mỗi phòng ban khác nhau bảo vệ sẽ nhìn thẻ và biết được bạn có quyền đi vào không.
Khi người dùng send một request lên server thì sẽ đính kèm với authentication_token
. Có hai cách để sử dụng token, thêm vào query string hoặc qua HTTP header.
Token authentication
có vẻ rất quan trọng, vậy phải làm sao?
Nắng đã có mũ, mưa đã có ô, lạnh cảm cúm đã có tiffi
, chưa có token auth đã có gem simple_token_authentication
Dạo đầu đủ rồi, bây giờ chúng ta sẽ bắt đầu thực hiện:
Tạo Rails app
rails new webservice_demo
Add gem và cài đặt
gem "devise"
gem "simple_token_authentication"
bundle install
Cài đặt model sử dụng Devise Authenticate
rails generate devise:install
rails generate devise User
Disable CRFS cho JSON request
application_controller.rb
protect_from_forgery with: :null_session
Tạo route cho API
Rails.application.routes.draw do
devise_for :users
namespace :api do
namespace :v1 do
devise_scope :user do
post "sign_up", :to => 'registrations#create'
post "sign_in", :to => 'sessions#create'
delete "sign_out", :to => 'sessions#destroy'
end
end
end
end
Tạo controller cho API
Trong thư mục app/controllers/api/v1
tạo các file:
applications_controller.rb
(Controller của route "api/v1/")
class Api::V1::ApplicationController < ActionController::API
acts_as_token_authentication_handler_for User, {fallback: :none}
respond_to :json
private
def current_user
@current_user ||= User.find_by authentication_token: request.headers["Authorization"] #token thông qua header
end
def authenticate_user_from_token
render json: {message: "You are not authenticated"},
status: 401 if current_user.nil?
end
end
def ensure_params_exist
return unless params[:user].blank?
render json: {message: "Missing params"}, status: 422
end
def load_user_authentication
@user = User.find_by_email user_params[:email]
return login_invalid unless @user
end
def login_invalid
render json:
{message: "Invalid login"}, status: 200
end
end
registrations_controller.rb
(Controller của route "api/v1/sign_up")
class Api::V1::RegistrationsController < Devise::RegistrationsController
before_action :ensure_params_exist
respond_to :json
def create
user = User.new user_params
if user.save
render json: {message: "Registration has been completed",user: user}, status: 200
else
warden.custom_failure!
render json: {message: error_messages(user.errors.messages), status: 200
end
end
private
def user_params
params.require(:user).permit :email, :password, :password_confirmation
end
end
sessions_controller.rb
(Controller của route "api/v1/sign_in")
class Api::V1::SessionsController < Devise::SessionsController
before_action :ensure_params_exist, only: [:create, :destroy]
before_action :load_user_authentication
respond_to :json
def create
if @user.valid_password? user_params[:password]
sign_in @user, store: false
render json: {message: "Signed in successfully",
user: @user, status: 200
return
end
invalid_login_attempt
end
def destroy
if @user.authentication_token == user_params[:authentication_token] #token thông qua query string
sign_out @user
render json: {message: "Signed out"}, status: 200
else
render json: {message: "Invalid token"}, status: 200
end
end
private
def user_params
params.require(:user).permit :email, :password, :authentication_token
end
def invalid_login_attempt
render json: {message: "Sign in failed"}, status: 200
end
end
Sau khi viết xong phần code cho server, bạn hãy sử dụng POSTMAN
để tạo các request tới server.
- Đăng ký: gửi request POST tới url /api/v1/sign_up với params
{
"email": "test@gmail.com",
"password": "12345678",
"password_confirmation": "12345678"
}
- Đăng nhập: gửi request POST tới url /api/v1/sign_in với params
{
"email": "test@gmail.com",
"password": "12345678"
}
- Đăng xuất: gửi request DELETE tới url /api/v1/sign_out với params
{
"authentication_token": "token của user"
}
Vậy là chúng ta đã tạo xong một API để thực hiện việc đăng ký, đăng nhập cho ứng dụng Rails server thông qua Devise. Bài viết đầu tiên chắc chắn sẽ còn nhiều thiếu xót, mong mọi người góp ý, bổ sung.
Thân ái và quyết thắng
All rights reserved