JWT در جنگو
برای داشتن سیستم Authentication حین ساخت API از چند روش میتوان استفاده کرد، به عنوان مثال میتوان به سیستم توکن خود Django Rest Framework یا سیستم JWT در جنگو اشاره کرد. JWT در واقع مخفف کلمات JSON Web Token بوده و یک JSON ساده است.
طبق JWT، RFC 7519 یک استاندارد باز برای انتقال امن اطلاعات میان طرفین و به صورت یک شی JSON راه امن و جامعی را تعریف میکند. بحث امضای دیجیتال پیش آمده و باید بگوییم که میتوان JWTها را توسط الگوریتم RSA یا ECDSA با یک کلید خصوصی /عمومی امضا کرد. JWTها در شکل متراکم خود دارای سه بخش هدر (Header)، Payload و امضا (Signature) هستند که با نقطه (.) از یکدیگر جدا میشوند.
نحوه کار JWT
از جمله مهمترین اصول پشت پرده طراحی کتابخانه جنگو میتوان به استقلال نسبی مولفههای مختلف این چارچوب، کدنویسی کمتر، اصل عدم تکرار، توسعه سریع و طراحی تمیز اشاره کرد. بنابراین اگر در ابتدای مسیر هستید یا حتی جز توسعهدهندههای خوب این راه هستید، یادگیری جنگو به شما دید بهتر و منطقی میدهد.
پس از ورود موفق یک کاربر، JSON Web Token به دست آمده و در حافظه محلی (Local Storage) دخیره میشود. هر بار که کاربر قصد دسترسی به یک URL محافظت شده داشته باشد، توکن در هدر درخواست ارسال میشود. سرور بررسیهای لازم را برای تایید JWT معتبر انجام داده و اگر تایید شود، به کاربر اجازه دسترسی داده میشود.
نمونهای از هدر محتوای معمول:
Authorization: Bearer eyJhbGciOiJIUzI1NiIsI
در نمودار زیر فرایند ذکر شده و ارتباط بین مرور گر و سرور به خوبی نشان داده شده است. برای درک خود JWT در جنگو مطالب بخشهای بعدی مفید خواهد بود.
نحوه نصب و راه اندازی JWT در جنگو
در مرحله اول نیاز به نصب JWT در پروژه است. از دستور زیر میتوان برای نصب JWT در جنگو استفاده کرد:
pip install djangorestframework-simplejwt
بعد از پایان نصب، دستورات زیر را در فایل settings.py اضافه کنید:
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': (
...
'rest_framework_simplejwt.authentication.JWTAuthentication',
)
{
همچنین برای urls.py:
from django.urls import path
from rest_framework_simplejwt import views as jwt_views
urlpatterns = [
# Your URLs...
path('api/token/', jwt_views.TokenObtainPairView.as_view(), name='token_obtain_pair'),
path('api/token/refresh/', jwt_views.TokenRefreshView.as_view(), name='token_refresh'),
]
چند نمونه کد
برای این آموزش از مسیر زیر و نمای API استفاده میشود:
views.py
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework.permissions import IsAuthenticated
class HelloView(APIView):
permission_classes = (IsAuthenticated,)
def get(self, request):
content = {'message': 'Hello, World!'}
return Response(content)
در ادامه استفاده از JWT در جنگو داریم:
urls.py
from django.urls import path
from myapi.core import views
urlpatterns = [
path('hello/', views.HelloView.as_view(), name='hello'),
]
استفاده از JWT در جنگو
در این آموزش برای استفاده از JWT در جنگو، از از HTTPie برای استفاده از نقاط پایانی (endpoints) API از طریق ترمینال استفاده خواهد شد. اما شما همچنین میتوانید از cURL (که به راحتی در بسیاری از سیستم عاملها موجود است) برای تست و آزمون موضوعات استفاده کنید.
یا به طور متناوب، با دسترسی به URL های نقطه پایانی مانند تصویر زیر از واسط وب DRF استفاده کنید:
توکن را به دست بیاور!
اولین قدم احراز هویت و به دست آوردن توکن است. بدین منظور نقطه پایانی یا همان End Point
/api/token/
بوده و فقط درخواستهای POST را قبول میکند.
http post http://127.0.0.1:8000/api/token/ username=vitor password=123
بنابراین، به طور کلی در بدنه پیام پاسخ، دو توکن است:
{
"access": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ0b2tlbl90eXBlIjoiYWNjZXNzIiwiZXhwIjoxNTQ1MjI0MjU5LCJqdGkiOiIyYmQ1NjI3MmIzYjI0YjNmOGI1MjJlNThjMzdjMTdlMSIsInVzZXJfaWQiOjF9.D92tTuVi_YcNkJtiLGHtcn6tBcxLCBxz9FKD3qzhUg8",
"refresh": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ0b2tlbl90eXBlIjoicmVmcmVzaCIsImV4cCI6MTU0NTMxMDM1OSwianRpIjoiMjk2ZDc1ZDA3Nzc2NDE0ZjkxYjhiOTY4MzI4NGRmOTUiLCJ1c2VyX2lkIjoxfQ.rA-mnGRg71NEW_ga0sJoaMODS5ABjE5HnxJDb0F8xAo"
}
پس از آن نیاز به ذخیره access token و refresh token در سمت کلاینت ( سرویس گیرنده در شبکه) است. برای دسترسی به نماهای محافظت شده در بکاند (به عنوان مثال، نقاط پایانی API که احتیاج به احراز هویت دارند)، باید access token را در هدر همه درخواستها قرار دهید، مانند این:
http http://127.0.0.1:8000/hello/ "Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ0b2tlbl90eXBlIjoiYWNjZXNzIiwiZXhwIjoxNTQ1MjI0MjAwLCJqdGkiOiJlMGQxZDY2MjE5ODc0ZTY3OWY0NjM0ZWU2NTQ2YTIwMCIsInVzZXJfaWQiOjF9.9eHat3CvRQYnb5EdcgYFzUyMobXzxlAVh_IAgqyvzCE"
این token دسترسی برای ۵ دقیقه بعدی معتبر بوده و پس از گدشت ۵ دقیقه تاریخ انقضایش به پایان میرسد. میدانیم که توکن به جهت تایید اعتبار حضور یک کاربر است. در یک مثال سادهتر، فرض کنید شما وارد یک همایش شدهاید. در مرحله اول و در هنگام ورود به سالن همایش، نام و نام کاربری خود را به مسئول مربوطه نشان داده و پس از تایید هویت شما، مسئول یک دستبند به منزله کاربر معتبر به شما میزند. در دفعات بعدی در صورت ورود و خروج به سالن، مسئول دیگر اعتبار هویت شما را چک نمیکند و فقط با داشتن دسبتند به شما اجازه ورود و خروج میدهد. اما برای حفظ امنیت بیشتر در سطح شبکه و وب، توکن دسترسی پس از مدتی منقضی شده و با خطای زیر روبرو خواهید شد:
http http://127.0.0.1:8000/hello/ "Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ0b2tlbl90eXBlIjoiYWNjZXNzIiwiZXhwIjoxNTQ1MjI0MjAwLCJqdGkiOiJlMGQxZDY2MjE5ODc0ZTY3OWY0NjM0ZWU2NTQ2YTIwMCIsInVzZXJfaWQiOjF9.9eHat3CvRQYnb5EdcgYFzUyMobXzxlAVh_IAgqyvzCE"
(Refresh token) در استفاده از JWT در django
برای داشتن توکن دسترسی جدید، لازم است از refresh token endpoint، استفاده شود:
/api/token/refresh/
برای ارسال refresh token داریم:
http post http://127.0.0.1:8000/api/token/refresh/ refresh=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ0b2tlbl90eXBlIjoicmVmcmVzaCIsImV4cCI6MTU0NTMwODIyMiwianRpIjoiNzAyOGFlNjc0ZTdjNDZlMDlmMzUwYjg3MjU1NGUxODQiLCJ1c2VyX2lkIjoxfQ.Md8AO3dDrQBvWYWeZsd_A1J39z6b6HEwWIUZ7ilOiPE
پاسخ برگشتی یک توکن دسترسی جدید است که از آن در ارتباطات بعدی استفاده خواهید کرد. جالب است بدانید در این فرایند، رفرش توکن برای ۲۴ ساعت بعدی معتبر بوده و پس از گذشت این زمان، باید فرایند احراز هویت برای دسترسی به توکن دسترسی و رفرش توکن با استفاده نام کاربری و کلمه عبور انجام بگیرد.
در نگاه اول شاید refresh token بی معنی به نظر برسد، اما در واقع لازم است مطمئن شوید که کاربر هنوز مجوزهای صحیح را دارد. اگر توکن دسترسی مدت زمان انقضای طولانی داشته باشد، امکان دارد به روز رسانی اطلاعات مربوط به توکن طول بکشد. زیرا چک و بررسی احراز هویت با رمزنگاری انجام میگیرد. به جای اینکه یک سری query به پایگاه داده زده شود و دادهها تایید گردند. بنابراین برخی از اطلاعات به نوعی کش( پنهان) میشوند.
با یک جنبه حالتی هم طرفیم، refresh token فقط با دیتای POST و access token با هدر HTTP ارسال میشود. که امکان دارد در طول مسیر وارد سیستم شود.
جمع بندی فریمورک JWT در جنگو
استفاده از JWT در جنگو برای احراز هویت روش مرسومی است. به طور کلی کتابخانه جنگو، یک چارچوب توسعه برنامههای کاربردی در زبان پایتون به حساب میآید. از جمله مهمترین اصول پشت پرده طراحی کتابخانه جنگو میتوان به استقلال نسبی مولفههای مختلف این چارچوب، کدنویسی کمتر، اصل عدم تکرار، توسعه سریع و طراحی تمیز اشاره کرد. بنابراین اگر در ابتدای مسیر هستید یا حتی جز توسعهدهندههای خوب این راه هستید، یادگیری فریمورک جنگو به شما دید بهتر و منطقی میدهد.