انواع احراز هویت(Authentication)
در فصل 3 از allauth و dj_rest_auth استفاده شد. به شخصه استفاده از کتابخانه ی دیگری را ترجیح میدهم. برای انتخاب کتابخانه بهتر است به بروز بودن کدهای کتابخانه ها، تعداد ستاره های گیتهاب و تجربه ی شخصی متوصل شوید.
لیست کتابخانه های معروف مربوط به API در جنگو را میتوانید از اینجا ببینید. در این قسمت قصد استفاده از djoser را دارم. به صورت کلی به نظر من djoser تجربه ی دولوپری بهتری نسبت به allauth و dj_rest_auth برای من رقم می زند.
بریم شروع کنیم!
ابتدا باید djoser را نصب کنید. با دستور زیر این کار را انجام دهید:
pipenv install djoser
سپس INSTALLED_APPS را به شکل زیر تغییر دهید.
INSTALLED_APPS = [
"home",
"search",
"wagtail.contrib.forms",
"wagtail.contrib.redirects",
"wagtail.contrib.routable_page",
"wagtail.embeds",
"wagtail.sites",
"wagtail.users",
"wagtail.snippets",
"wagtail.documents",
"wagtail.images",
"wagtail.search",
"wagtail.admin",
"wagtail",
"modelcluster",
"taggit",
"django.contrib.admin",
"django.contrib.auth",
"django.contrib.contenttypes",
"django.contrib.sessions",
"django.contrib.messages",
"django.contrib.staticfiles",
# 3rd Party
# "debug_toolbar",
"rest_framework", # new
# "rest_framework.authtoken",
# "rest_framework_simplejwt",
"djoser", # new
# "corsheaders",
"storages",
# development
"blog",
"likesncommenets",
]
دقت کنید که rest_framework با خود wagtail نصب شده است و نیازی به نصب جداگانه ی آن ندارید. در مرحله ی بعدی باید اندپوینا های urlpatterns را اصلاح کنید دقت کنید که این url جدید قبل از wagtail_urls قرار بگیرد.تمام شد! سرویس Authentication حالا آماده ی استفاده است.
from django.conf import settings
from django.urls import include, path
from django.contrib import admin
from wagtail.admin import urls as wagtailadmin_urls
from wagtail import urls as wagtail_urls
from wagtail.documents import urls as wagtaildocs_urls
from search import views as search_views
urlpatterns = [
path("django-admin/", admin.site.urls),
path("admin/", include(wagtailadmin_urls)),
path("documents/", include(wagtaildocs_urls)),
path("search/", search_views.search, name="search"),
path("api/v1/auth/", include("djoser.urls")), # new
path("api/v1/auth/", include("djoser.urls.authtoken")), # new
]
if settings.DEBUG:
from django.conf.urls.static import static
from django.contrib.staticfiles.urls import staticfiles_urlpatterns
# Serve static and media files from development server
urlpatterns += staticfiles_urlpatterns()
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
urlpatterns = urlpatterns + [
# For anything not caught by a more specific rule above, hand over to
# Wagtail's page serving mechanism. This should be the last pattern in
# the list:
path("", include(wagtail_urls)),
# Alternatively, if you want Wagtail pages to be served from a subpath
# of your site, rather than the site root:
# path("pages/", include(wagtail_urls)),
]
bug!!
چند مسئله وجود دارد.
- باید ایمیل های مناسب خود را ارسال کنیم و سرویس ایمیل را راه اندازی کنیم.
- باید تنظیمات مورد نیاز djoser را ست کنیم.
- بسیاری از تنظیمات djoser برای ساختارهای داخلی خود جنگو هستند(serializer و get_user) و در صورت تغییر آنها باید تنظیمات بیشتری را به پروژه اضافه کنیم.
به تنظیمات پیشنهادی دقت کنید:
DJOSER = {
"PASSWORD_RESET_CONFIRM_URL": "password/reset/confirm/{uid}/{token}/",
"PASSWORD_RESET_SHOW_EMAIL_NOT_FOUND": True,
"SEND_ACTIVATION_EMAIL": True,
"ACTIVATION_URL": "activate/{uid}/{token}/",
}
در حال حاضر خروجی ایمیل را در ترمینال میبینید اگر به اندپوینت api/v1/auth/users/ درخواست POST بفرستید. بیایید همه چیز را درست کنیم.
{% load i18n %}
{% block subject %}
{% blocktrans %}فعالسازی حساب کاربری{% endblocktrans %}
{% endblock subject %}
{% block text_body %}
{% blocktrans %}سلام،<br />برای فعال سازی اکانت خود در وبسایت {{ site_name }} روی لینک زیر کلیک کنید.{% endblocktrans %}
{% trans "" %}
https://{{ domain }}/{{ url|safe }}
{% trans "به خانواده کدینگ کاگز خوش آمدید" %}
{% blocktrans %}{{ site_name }} تیم{% endblocktrans %}
{% endblock text_body %}
{% block html_body %}
<div style="direction:rtl;">
<h1>فعالسازی حساب کاربری</h1>
<p>{% blocktrans %}سلام،<br />برای فعال سازی اکانت خود در وبسایت {{ site_name }} روی لینک زیر کلیک کنید.{% endblocktrans %}</p>
<p>{% trans "" %}</p>
<p><a href="https://{{ domain }}/{{ url|safe }}">https://{{ domain }}/{{ url|safe }}</a></p>
<h4>{% trans "به خانواده کدینگ کاگز خوش آمدید" %}</h4>
<p>{% blocktrans %}تیم {{ site_name }}{% endblocktrans %}</p>
</div>
{% endblock html_body %}
{% load i18n %}
{% block subject %}
{% blocktrans %}بازیابی رمز عبور{% endblocktrans %}
{% endblock subject %}
{% block text_body %}
{% blocktrans %}سلام {{ user.get_username }} شما این ایمیل را به منظور بازیابی رمز عبور خود در سایت {{ site_name }} دریافت کردهاید.{% endblocktrans %}
{% trans "روی لینک زیر کلیک کنید تا رمز عبورتان را بازیابی کنید:" %}
{{ protocol }}://{{ domain }}/{{ url }}
{% trans "" %}
{% trans "مرسی که هستی :)" %}
{% blocktrans %}{{ site_name }} تیم{% endblocktrans %}
{% endblock text_body %}
{% block html_body %}
<div style="direction:rtl;">
<p>{% blocktrans %}سلام <b>{{ user.get_username }}</b> شما این ایمیل را به منظور بازیابی رمز عبور خود در سایت {{ site_name }} دریافت کردهاید.{% endblocktrans %}</p>
<p>{% trans "روی لینک زیر کلیک کنید تا رمز عبورتان را بازیابی کنید:" %}</p>
<a href="{{ protocol }}://{{ domain }}/{{ url }}">{{ protocol }}://{{ domain }}/{{ url }}</a>
<p>{% trans "" %}</p>
<p>{% trans "مرسی که هستی :)" %}</p>
<p>{% blocktrans %}تیم {{ site_name }}{% endblocktrans %}</p>
</div>
{% endblock html_body %}
تمرین 1
داکیومنت های django-rest-knox را بخوانید و آن را نصب و محدودیت هایی برای تعداد دستگاه های کاربران اعمال کنید. بد نیست اگر کمی با تنظیمات این کتابخانه ور بروید.
تمرین 2
به صفحه ی مربوط به پیاده سازی JWT بروید و آن را پیاده کنید. تنظیمات مربوطه اینجاست:
https://djoser.readthedocs.io/en/latest/authentication_backends.html#json-web-token-authentication
ضمنا اگر پکیج Simple JWT را نصب ندارید باید آن را نصب کنید.
با تنظیمات لازم، ویژگی های JWT دریافت شده را تغییر دهید.
تنظیمات پیشنهادی برای دستکاری :
- ACCESS_TOKEN_LIFETIME
- REFRESH_TOKEN_LIFETIME
- SIGNING_KEY
- AUTH_HEADER_TYPES
- AUTH_HEADER_NAME
تمرین 3
به سراغ تنظیمات مربوط به Social Endpoints بروید و ثبت نام با گوگل(یا یک پروایدر دیگر) را پیاده سازی کنید.
تمرین 4
تمرین 5
در حال حاضر توکن JWT ما در body درخواست JWT Create باز می گردد. متاسفانه هیچکدام از پکیج های معروف و پایدار به شکل امن تر httpOnly این توکن را باز نمیگرداند. معمولا این مسئله را میتوان توسط Server Endpoint ها در فرانت اند هندل کرد. سعی کنید ست کنید با بازنویسی view های مربوط به Simple JWT که از اینجا میتوانید ببینید و با کمی سرچ و جست و جو و وَر رفتن، یک اندپوینت جدید بنویسید که به صورت اتوماتیک در خروجی Header مناسب را به شکل httpOnly باز گرداند.
البته در حالت واقعی استفاده از Server Endpoint ها در فرانت اند کم دردسر تر است ولی اگر امکان یا سواد نوشتن Server Endpoint ها در تیم شما نباشد، بلاخره باید این کار یک جا انجام شود!
راهنمایی:
def httponly_view(request):
response = Response(serializer.data)
response.set_cookie('cookie_name', 'cookie_value', httponly=True)
return response
راه حل دیگر:
بازگشت به dj-rest-auth