實戰講解 Django-rest-framework JWT 用戶認證開發

MedusaSorcerer的博客


咱們用 Djangorest-framework 開發用戶模塊, 並使用 JWT(Json Web Token) 進行用戶認證, 該項目將上傳在 MedusaSorcerer/django-restframework-demo 上供你們借鑑和使用。python

開發環境:Windows10
開發 IDE:Pycharm
開發框架:Django
開發語言:Pythonmysql

requirements

python==3.8.2
django==3.0.6
django-restframework
django-restframesork-jwt
複製代碼

建立 Django 項目

CMD 命令行界面, 建立 Django 項目程序 Medusagit

python3 -m django startproject Medusa
複製代碼

Medusa 根目錄下建立應用總模塊 applicationsgithub

cd Medusa
mkdir applications
複製代碼

進入 applications 建立應用模塊 User, 這兒採用傻瓜式操做, 建立層級 Django-APPsql

cd applications
python3 ../manage.py startapp User
複製代碼

此時項目結構以下: shell

修改配置

修改 applications/User/apps.py數據庫

from django.apps import AppConfig


class UserConfig(AppConfig):
    name = 'applications.User'
複製代碼

在項目根目錄新建配置文件夾 config, 並添加配置文件 config.pydjango

cd ..
mkdir config
cd config
type NUL > config.py
複製代碼

config/config.py 新增如下配置內容:json

#!/usr/bin/env python
# _*_ Coding: UTF_8 _*_

# MySQL 服務地址
MYSQL_SERVER_HOST = '127.0.0.1'

# MySQL 服務端口
MYSQL_SERVER_PORT = '3306'

# MySQL 數據庫名稱
MYSQL_DATABASE_NAME = 'medusa'

# MySQL 數據庫鏈接用戶帳號
MYSQL_SERVER_USERNAME = 'root'

# MySQL 數據庫鏈接用戶密碼
MYSQL_SERVER_PASSWORD = 'mysql-password'
複製代碼

修改 Medusa/settings.py 中配置參數 ALLOWED_HOSTSapi

ALLOWED_HOSTS = ['*']
複製代碼

添加 Medusa/settings.py 中應用註冊參數 INSTALLED_APPS

INSTALLED_APPS = [
    ...,
    'applications.User',
]
複製代碼

Medusa/settings.py 頂部導入配置文件:

from config import config
複製代碼

Medusa/setting.py 中修改配置數據庫參數 DATABASES

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': config.MYSQL_DATABASE_NAME,
        'USER': config.MYSQL_SERVER_USERNAME,
        'PASSWORD': config.MYSQL_SERVER_PASSWORD,
        'HOST': config.MYSQL_SERVER_HOST,
        'PORT': config.MYSQL_SERVER_PORT,
    }
}
複製代碼

Medusa/setting.py 中修改配置時區參數 TIME_ZONE:

TIME_ZONE = 'Asia/Shanghai'
複製代碼

固然你能夠繼續在 Medusa/settings.py 修改語言參數, 咱們建立的項目暫不修改:

LANGUAGE_CODE = 'zh-hans'
複製代碼

確保你的 MySQL 中已經存在了你配置的數據庫名稱對應的數據庫, 而且能夠鏈接成功, 就能夠嘗試在 Medusa 根目錄下啓動 Django 項目,:

python3 manage.py runserver 0.0.0.0:8000
複製代碼

你若是執行成功你能夠訪問 http://127.0.0.1:8000/ 就看到如下界面:

建立 User 模型

applications/User/models.py 中自定義咱們的用戶模型類

from django.contrib.auth.models import AbstractUser


class User(AbstractUser):
    class Meta:
        db_table = 'medusa_user'
        ordering = ('-id',)
複製代碼

咱們採用的是繼承 AbstractUser 類並指定 db_table 的方式, 此時你可使用 PycharmCtrl + B 進入父類中查看 User 具備的屬性和方法。

固然了, 在執行到這個步驟的時候其實用戶的模型類並無生效, 而須要達到生效的效果則是須要指定用戶模型類的位置參數, 你只須要在 Medusa/settings.py 中用 AppName.UserModelsName 的方式指定用戶模型類便可:

AUTH_USER_MODEL = 'User.User'
複製代碼

有關於用戶認證的模型類介紹, 推薦你查閱 Customizing authentication in Django

使用 Django 遷移命令遷移數據庫生成數據表:

python3 manage.py makemigrations
python3 manage.py migrate
複製代碼

你可使用 MySQL 數據庫鏈接應用查看你生成的數據表。

登陸認證

在準備好基本環境後咱們進行登陸接口的開發工做, 登陸的接口主要是對用戶進行驗證以及口令的返回, 使用 JWT 驗證的時候先安裝導入須要的包應用 rest_framework, 添加 Medusa/settings.py 中應用註冊參數 INSTALLED_APPS

INSTALLED_APPS = [
    ...,
    'rest_framework',
]
複製代碼

applications/User/ 下建立用戶認證的視圖文件 userauth.py 並撰寫用戶登陸認證視圖類:

#!/usr/bin/env python
# _*_ Coding: UTF-8 _*_
from rest_framework_jwt.serializers import JSONWebTokenSerializer
from rest_framework_jwt.views import JSONWebTokenAPIView


class UserLoginAPIView(JSONWebTokenAPIView):
    serializer_class = JSONWebTokenSerializer
複製代碼

簡簡單單的幾行代碼就實現了一個用戶登陸的接口, 你如今就須要在你的路由管理器裏面註冊這個登陸的 API 試圖便可, 在 Medusa/urls.pyurlpatterns 參數中註冊路由:

urlpatterns = [
    path('api/v1.0.0/user/login', userauth.UserLoginAPIView.as_view())
]
複製代碼

不要着急, 咱們是否是尚未建立用戶呢?

python3 manage.py createsuperuser
複製代碼

依次輸入:

  1. Username
  2. Email address
  3. Password
  4. Password(again)

由於我輸入的密碼是 admin, 因此在建立的時候給了三個警告信息, 須要你確認信息後再次確認:

The password is too similar to the username.
This password is too short. It must contain at least 8 characters.
This password is too common.
複製代碼
  • 密碼和用戶名的類似度太高
  • 密碼長度過短, 應該至少是八個字符
  • 密碼屬於弱密碼

無論他, 上去就是一個 y 給他:

是時候啓動服務測試下咱們的代碼成果了:

登陸註銷

對於已經登陸的用戶實現登出功能, 主要的是在於登陸的一種身份判斷, 那等同於一個惟一字段能實現判斷登陸用戶登出後變化, 而且從新生成這個惟一字段。

咱們在 User 類中加入這樣一條字段配置:

from uuid import uuid4

user_secret = models.UUIDField(default=uuid4())
複製代碼

注意 user_secretUser 類的一個屬性, 你可能會想那我是否是要從新實現喲用戶登陸的邏輯呢? 答案是不須要的, 由於咱們建立的字段, 咱們用函數路徑的方式指定原先的函數, 咱們將採用重寫本來的判斷函數便可實現:

在項目根目錄下的 applications/User/views.py 中建立函數, 函數位置可自行肯定, 你也能夠建立一個 .py 文件:

#!/usr/bin/env python
# _*_ Coding: UTF-8 _*_


def get_user_secret(user):
    return user.user_secret
複製代碼

主要的內容是在 Medusa/settings.py 中配置函數路徑:

JWT_AUTH = {
    'JWT_GET_USER_SECRET_KEY': 'applications.User.views.get_user_secret'
}
複製代碼

由於咱們修改了模型類, 因此咱們須要對數據庫進行再次遷移:

python3 manage.py makemigrations
python3 manage.py migrate
複製代碼

applications/User/userauth.py 中建立登出視圖:

import uuid

from rest_framework import status, views
from rest_framework.response import Response


class UserLogoutAPIView(views.APIView):
    def get(self, request, *args, **kwargs):
        user = request.user
        user.user_secret = uuid.uuid4()
        user.save()
        return Response({'detail': 'login out.', 'status': status.HTTP_200_OK}, status=status.HTTP_200_OK)
複製代碼

在路由模塊 Medusa/urls.py 中註冊:

urlpatterns = [
    ... ,
    path('api/v1.0.0/user/logout', userauth.UserLogoutAPIView.as_view()),
]
複製代碼

測試一下:

NotImplementedError: Django doesn't provide a DB representation for AnonymousUser.
複製代碼

What? 報錯了, 由於咱們訪問 API 的時候沒有使用認證信息, 因此訪問的 User 對象是一個匿名用戶對象, 因此咱們須要對這個接口採起認證:

from rest_framework.permissions import IsAuthenticated


class UserLogoutAPIView(views.APIView):
    permission_classes = [IsAuthenticated]
    
    def get(self, request, *args, **kwargs):
        ...
複製代碼

添加認證參數 permission_classes 表示須要 IsAuthenticated 已認證的對象才能夠訪問, 再次嘗試接口會收到如下 json 提示:

{
    "detail": "Authentication credentials were not provided."
}
複製代碼

認證失敗? 咱們在 Medusa/settings.py 中添加如下配置信息:

import datetime


JWT_AUTH = {
    # 以前配置的用戶依據判斷函數路由
    'JWT_GET_USER_SECRET_KEY': 'applications.User.views.get_user_secret',
    
    # 用戶認證數據的過時時間
    'JWT_EXPIRATION_DELTA': datetime.timedelta(days=1)
}
REST_FRAMEWORK = {
    # 用戶認證類
    'DEFAULT_AUTHENTICATION_CLASSES': (
        # 優先使用 JWT 的方式認證用戶
        'rest_framework_jwt.authentication.JSONWebTokenAuthentication',
        'rest_framework.authentication.SessionAuthentication',
        'rest_framework.authentication.BasicAuthentication',
    ),
}
複製代碼

{
    "detail": "login out.",
    "status": 200
}
複製代碼

建立用戶

在建立用戶的時候咱們不會使用命令行來建立用戶的, 使用模型類的時候建立用戶通常會這樣來實現, 固然了, 這兒咱們省略了一些操做, 僅僅介紹建立用戶的快捷方式:

from applications.User.models import User


User.objects.create_user(username=username, email=email, password=password, **extra_fields)
User.objects.create_superuser(username=username, email=email, password=password, **extra_fields)
複製代碼

後面攜帶的 **extra_fields 可讓你攜帶更多的 Models 指定的字段, 若是你須要的話。

該描述內容有些省略的地方或者描述不清的地方請留言
代碼已經同步至 Github 地址:MedusaSorcerer/django-restframework-demo 今天你進步了嗎?

相關文章
相關標籤/搜索