سلام، در این مقاله میخوایم راجع به Authentication و authorize با JWT صحبت کنیم. در واقع این قسمت دوم از Authentication & Authorize in Ruby on Rails هست. پس حتما قسمت اول رو بخونین و بعد بیاین سراغ قسمت دوم.
همچنین شما میتونین از طریق گیت هابم یعنی از اینجا به این پروژه دسترسی داشته باشید.
من همچنان ترجیح میدم در کنار این پروژه هم، چای لاهیجان بنوشم و لذت ببرم (:
برای شروع درون فایل Gemfile رفته و 'gem 'jwt رو در این فایل اضافه کنین.
خب دستور bundle install رو بزنین که gem های جدید نصب بشن.
ممنون!
در ابتدا چند متد رو خدمتتون توضیح میدم، سپس این توابع رو در پروژه به کار میبریم.
def encode_token(payload) JWT.encode(payload, 's3cr3t') end
متد encode جزئی از JWT است و ما به وسیله encode، یک token میسازیم. این متد دو آرگومان میگیره. اولین آرگومان یه hash هستش و دومی یه secret هست. دقت کنین از secretی که در encode استفاده میکنیم، در decode هم باید از همین secret استفاده کنیم.
def decode_token if auth_header token = auth_header.split(' ')[1] begin JWT.decode(token, 's3cr3t', true, algorithm: 'HS256') rescue JWT.DecodeError nil end end end
متد decode هم جزئی از JWT هست و ما به وسیله ی متد decode، اطلاعاتی از token بیرون می اوریم. در واقع این اطلاعات، همان objectی است که به متد encode دادیم تا tokenی برای ما بسازد.
این متد چهار آرگومان میگیرد. اولی tokenی که ساخته بودیم است، دومی secretی است که هنگام encode داده بودیم، سومی یک مقدار true است و در نهایت الگوریتمی که میخوایم باهاش decode انجام بشه.
def auth_header # { Authorization: 'Bearer <token>' } request.headers['Authorization'] end
وقتی ما sign-up یا log-in انجام میدیم، یه tokenی میگیریم. این token رو باید در هر requestی بفرستیم تا system تشخیص بده که ما log-in کردیم یا نه.
از متد auth_header استفاده میکنیم تا token فرستاده شده رو به دست بیاریم.
برای اینکه token رو درset ،postman کنیم، باید در قسمت Authorization، تایپش رو به <Bearer <token تغییر بدیم و همچنین tokenی که داریم رو در قسمت token پیست میکنیم.
همونطور که در قسمت اول خدمتتون عرض کردم، همه ی کنترولر ها از ApplicationController ارث میبرند، ما این سه تابعی که در بالا توضیح دادم رو در همین کنترولر قرار میدیم.
class ApplicationController < ActionController::API before_action :authorize protected def authorize render json: { message: ['Please log in'] }, status: 401 unless User.find(session[:user_id]) if decode_token user_id = decode_token[0]['user_id'] render json: { message: ['Please log in'] }, status: 401 unless User.find(user_id) else render json: { message: ['Please log in'] }, status: 401 end end def encode_token(payload) JWT.encode(payload, 's3cr3t') end def decode_token if auth_header token = auth_header.split(' ')[1] begin JWT.decode(token, 's3cr3t', true, algorithm: 'HS256') rescue JWT.DecodeError nil end end end def auth_header # { Authorization: 'Bearer <token>' } request.headers['Authorization'] end end
در قسمت authorize علاوه بر اینکه از طریق session به ID کاربر یا user دسترسی پیدا می کنیم، از طریق encode کردن token به ID مورد نظر نیز دسترسی پیدا میکنیم.
در کنترولر session هم از این متد ها به صورت زیر استفاده میکنیم.
class SessionsController < ApplicationController skip_before_action :authorize def create @user = User.find_by( email: params[:email] ) if @user.try(:authenticate, params[:password]) token = encode_token({ user_id: @user.id }) render json: {user: @user, token: token}, status: 200 else render json: { message: ['Invalid user/password combination'] }, status: 400 end end def destroy session[:user_id] = nil render json: { message: ['Logged out'] }, status: 200 end end
در متد create، علاوه بر اینکه ID کاربر رو در session ذخیره می کنیم، از ID برای ساخت token هم استفاده میکنیم.