Chúng ta sẽ sử dụng Knock làm nền tảng cho Authorization API.
Bước 1__Thiết lập ứng dụng:
Khi bạn đã sẵn sàng, hãy mở terminal và nhập các lệnh sau đây:
# Lệnh này sẽ tạo ra 1 ứng dụng Rails với API mode. # Trong ví dụ này chúng ta sẽ sử dụng MySQL làm cơ sở dữ liệu. rails new auth-api --api -d mysql # Di chuyển đến thử mục của ứng dụng cd auth-api
Bây giờ bạn đã tạo được ứng dụng và đã chuyển hướng đến thư mục của ứng dụng, hãy mở Gemfile của bạn lên và thêm các gem sau đây:
# auth-api/Gemfile gem 'bcrypt', '~> 3.1.7' gem 'active_model_serializers' gem 'rack-cors' gem 'knock' gem 'jwt'
Nó sẽ trông giống Gemfile dưới đây:
Tiếp theo , chúng ta sẽ chạy các lệnh dưới đây trong terminal. Chúng ta sẽ hoàn thành việc thiết lập cấu trúc cơ bản cho ứng dụng.
bundle install # Chạy lệnh này để thiết lập cấu trúc Knock cơ bản. rails generate knock:install rails generate knock:token_controller user # Tiếp theo chạy các lệnh sau đây để chuẩn bị cho ứng dụng Rails của bạn rails generate model users rails generate controller users rails generate controller home rails g serializer user rails db:create
Bước 2__Thiết lập cơ sở dữ liệu
Bây giờ chúng ta sẽ thiết lập bảng Users cho ứng dụng. Do chúng ta chỉ tạo một hệ thống cơ bản nên chúng ta sẽ giữ cơ sở dữ liệu đơn giản nhất có thể.
Knock sử dụng trường địa chỉ email cho mục đích xác minh. Chúng ta sẽ sử dụng trường role để cung cấp cho ứng dụng một hệ thống phân quyền đơn giản.
Mở tệp dưới đây và thêm vào đoạn code sau
# File location: # - project_name/db/migrate/:random_number_create_users.rb
class CreateUsers < ActiveRecord::Migration[5.1] def change create_table :users do |t| t.string :username, null: false, unique: true t.string :email, null: false, index: true, unique: true t.string :password_digest t.string :role, null: false, default: 'user' t.datetime :last_login t.timestamps end end end
Nhập dòng lệnh sau trong terminal để tạo bảng User:
rails db:migrate
Bước 3__Thiết lập Authorization/Knock
Đầu tiên chúng ta sẽ cấu hình Knock cho ứng dụng của chúng ta. Knock làm cho quá trình này trở lên đơn giản, bạn chỉ cần bỏ comment cách thiết lập mà bạn muốn sử dụng.
Đảm bảo các dòng dưới đây không bị comment trong tệp của bạn:
# File Location: # - project_name/config/initializers/knock.rb Knock.setup do |config| # Set how long a login token is valid. config.token_lifetime = 1.week config.token_signature_algorithm = 'HS256' config.token_secret_signature_key = -> { Rails.application.secrets.secret_key_base } config.not_found_exception_class_name = 'ActiveRecord::RecordNotFound' end
Tiếp theo chúng ta cần thiết lập cho User model. Chúng ta sẽ thiết lập một số validations và phương thức để sử dụng sau.
# File Location: # - project_name/app/model/user.rb class User < ApplicationRecord # Necessary to authenticate. has_secure_password # Basic password validation, configure to your liking. validates_length_of :password, maximum: 72, minimum: 8, allow_nil: true, allow_blank: false validates_confirmation_of :password, allow_nil: true, allow_blank: false before_validation { (self.email = self.email.to_s.downcase) && (self.username = self.username.to_s.downcase) } # Make sure email and username are present and unique. validates_presence_of :email validates_presence_of :username validates_uniqueness_of :email validates_uniqueness_of :username # This method gives us a simple call to check if a user has permission to modify. def can_modify_user?(user_id) role == 'admin' || id.to_s == user_id.to_s end # This method tells us if the user is an admin or not. def is_admin? role == 'admin' end end
Bây giờ, chúng ta sẽ thiết lập tất cả các controllers cần thiết cho Authentication API.
# File Location: # - project_name/app/controller/application_controller.rb class ApplicationController < ActionController::API # Include Knock within your application. include Knock::Authenticable protected # Method for checking if current_user is admin or not. def authorize_as_admin return_unauthorized unless !current_user.nil? && current_user.is_admin? end end
# File Location: # - project_name/app/controller/home_controller.rb class HomeController < ApplicationController # authenticate_user is now a resource you can use on any method to make sure the client is authorized before_action :authenticate_user, only: [:auth] # Public method def index render json: { service: 'auth-api', status: 200 } end # Authorized only method def auth render json: { status: 200, msg: "You are currently Logged-in as #{current_user.username}" } end end
Bước 4__Thiết lập User
Tiếp theo, chúng ta sẽ tạo các phương thức để tạo tài khoản và xử lý xác thực. Đây là các phương thức cơ bản cần thiết để bắt đầu thử nghiệm API của chúng ta.
# File Location: # - project_name/app/controller/users_controller.rb class UsersController < ApplicationController # Use Knock to make sure the current_user is authenticated before completing request. before_action :authenticate_user, only: [:index, :current, :update] before_action :authorize_as_admin, only: [:destroy] before_action :authorize, only: [:update] # Should work if the current_user is authenticated. def index render json: {status: 200, msg: 'Logged-in'} end # Call this method to check if the user is logged-in. # If the user is logged-in we will return the user's information. def current current_user.update!(last_login: Time.now) render json: current_user end private # Setting up strict parameters for when we add account creation. def user_params params.require(:user).permit(:username, :email, :password, :password_confirmation) end # Adding a method to check if current_user can update itself. # This uses our UserModel method. def authorize return_unauthorized unless current_user && current_user.can_modify_user?(params[:id]) end end
Bây giờ chúng ta sẽ thêm một số phương thức cơ bản để tạo và quản lý người dùng. Điều này sẽ cung cấp cho người dùng quyền truy cập để tạo và cập nhật tài khoản và cấp cho quản trị viên khả năng xóa người dùng.
# Phương thức tạo người dùng sử dụng params an toàn def create user = User.new(user_params) if user.save render json: {status: 200, msg: 'User was created.'} end end # Phương thức cập nhật người dùng. Người dùng cần phải được ủy quyền. def update user = User.find(params[:id]) if user.update(user_params) render json: { status: 200, msg: 'User details have been updated.' } end end # Phương thức xóa người dùng, chỉ dành cho admin def destroy user = User.find(params[:id]) if user.destroy render json: { status: 200, msg: 'User has been deleted.' } end end
Cuối cùng, chúng ta cần chỉnh sửa User Serializer mà chúng ta tạo lúc đầu. Chúng ta sẽ sử dụng serializer để tránh việc gửi dữ liệu từ API của chúng ta.
# File Location: # - project_name/app/serializers/user_serializer.rb class UserSerializer < ActiveModel::Serializer attributes :id, :email, :username, :role, :created_at, :updated_at, :last_login end
Bước 5__Hoàn thành và Chạy thử
Chúng ta cần phải thêm các routes cho API của chúng ta trước khi chạy thử.
# File Location: # - project_name/config/routes.rb Rails.application.routes.draw do # Home controller routes. root 'home#index' get 'auth' => 'home#auth' # Get login token from Knock post 'user_token' => 'user_token#create' # User actions get '/users' => 'users#index' get '/users/current' => 'users#current' post '/users/create' => 'users#create' patch '/user/:id' => 'users#update' delete '/user/:id' => 'users#destroy' end
Bây giờ tất các các routes đã được thêm, đã đến lúc bắt đầu ứng dụng trên môi trường local
# Open Terminal and enter:
Rails s -p 5000
Khi test API, chúng ta sẽ sử dụng ứng dụng Postman. Postman là một công cụ miễn phí và đơn giản để test API.
Xem chi tiết hơn về Postman
Đầu tiên, hãy bắt đầu bằng các thử tạo người dùng. Chúng ta chỉ cần đặt body bằng thông chi tiết của một tài khoản mới.
Tiếp theo, hãy thử test phần đăng nhập mà chúng ta đã tạo.
Nếu mọi thứ đã hoạt động bình thường, chúng ta sẽ nhận được JWT Token từ Knock, trông giống như kết quả dưới đây.
Bây giờ chúng ta đã có JWT token, hãy thử ủy quyền với token đã tạo của chúng ta. Để gửi token tới API, chúng ta cần thêm Authorization key với định dạng sau:
Bearer generated_key
Postman của bạn sẽ trông giống cài đặt dưới đây.
Khi bạn đã thêm Authorization key, nhấn button send. Bạn sẽ nhận được status: 200 và message mà chúng ta thiết lập trong HomeController
Tiếp theo, hãy đảm bảo hệ thống ủy quyền của chúng ta hoạt động bình thường. Bắt đầu bằng cách bỏ Authorization key đã thiết lập trước đó. Sau khi bị vô hiệu hóa, hãy thử gửi lại yêu cầu và xem bạn có nhận lại được status: 401 Unauthorized
Thank for reading~!
Link nguồn của tác giả James Kropp: https://engineering.musefind.com/building-a-simple-token-based-authorization-api-with-rails-a5c181b83e02