django-4-登陆设计与鉴权

一、用户登录

1.1 接口设计

1.1.1 用户登录接口设计

POST /users/login/

Body 请求参数

{
  "username": "xinlan",
  "password": "123456" 
}

请求参数

名称

位置

类型

必选

中文名

说明

body

body

object

none

» username

body

string

用户名

用户名

» password

body

string

密码

密码

返回示例

成功

{
  "refresh": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ0b2tlbiI6InJlZnJlc2giLCJleHAiOjE2MTQ4NTIyODQsImp0aSI6IjkwNWEzOTdiYTQ0ODQ1OTRiZTU1MDI4NmJjNWJiZjIwIiwidXNlcl9pZCI6MX0.WktTD8vABca5nQ0c9RB-KNOsaV-E7_ziQnjezndRzkk",
  "token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ0b2tlbiI6ImFjY2VzcyIsImV4cCI6MTYxNDc2NjE4NCwianRpIjoiZDk2MjFmZjhkMWNjNGJhODlkNTExNTQw·YjdlMTQ5ZjQiLCJ1c2VyX2lkIjoxfQ.IcCRz9kxGlwKTfCeScwGsWEjhoxPBbP6_HT3TMwBZHM"
}

返回结果

状态码

状态码含义

说明

数据模型

200

OK

成功

Inline

返回数据结构

状态码 200

名称

类型

必选

约束

中文名

说明

» refresh

string

true

none

刷新token

none

» token

string

true

none

token

none

1.1.2 token刷新接口设计

POST /users/token/refresh/

Body 请求参数

{
  "refresh": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ0b2tlbl90eXBlIjoicmVmcmVzaCIsImV4cCI6MTYzMDkzMzEwMywianRpIjoiNzc3YTg3OWYyZTM4NGExYzhlYjFhYzVhMTA5ZTU4MGQiLCJ1c2VyX2lkIjoxfQ.8duDfoZmUJBjqgyyJQqANKl5zcHpZDN8phuNoGFQBm8"
}

请求参数

名称

位置

类型

必选

中文名

说明

body

body

object

none

» refresh_token

body

string

刷新token值

刷新token值

返回示例

成功

{
  "token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ0b2tlbl90eXBlIjoiYWNjZXNzIiwiZXhwIjoxNjMwOTk1NDY3LCJqdGkiOiI2YTIwZmIwZGZmZDA0YTJiYTAwOWM0YjNjNTQ2NjZkOCIsInVzZXJfaWQiOjF9.tdCvibq2d8ts_uCbqAvCVr1JOymdbHw7HLB7QckzbUs"
}

返回结果

状态码

状态码含义

说明

数据模型

200

OK

成功

Inline

返回数据结构

状态码 200

名称

类型

必选

约束

中文名

说明

» token

string

true

none

token

token

二、重写验证视图

simplejwt 已经实现了验证视图,但我们的项目中需要修改返回数据结构,所以要重写视图。

1. 在 users/ 下创建 serializers.py 模块,编写如下代码:

from rest_framework import serializers

from rest_framework_simplejwt.serializers import TokenObtainPairSerializer, TokenRefreshSerializer

from .models import User


class MyTokenSerializer(TokenObtainPairSerializer):
    def validate(self, attrs):
        data = super().validate(attrs)

        # 修改access为token
        data['token'] = data.pop('access')
        # 添加额外数据
        data['username'] = self.user.username
        data['id'] = self.user.id
        data['msg'] = '登录成功'
        return data


class MyRefreshTokenSerializer(TokenRefreshSerializer):
    def validate(self, attrs):
        data = super().validate(attrs)
        data['token'] = data.pop('access')
        return data


class UserSerializer(serializers.ModelSerializer):
    class Meta:
        model = User
        fields = ['id', 'username', 'password', 'mobile', 'is_staff', 'is_superuser']

2. 在 users/views.py 中编写如下视图:

from rest_framework.viewsets import ModelViewSet
from rest_framework.permissions import IsAuthenticated

from rest_framework_simplejwt.views import TokenObtainPairView, TokenRefreshView as TRV

from .serializers import MyTokenSerializer, MyRefreshTokenSerializer, UserSerializer
from .models import User


class LoginView(TokenObtainPairView):
    serializer_class = MyTokenSerializer


class TokenRefreshView(TRV):
    serializer_class = MyRefreshTokenSerializer


class UserViewSet(ModelViewSet):
    queryset = User.objects.all()
    serializer_class = UserSerializer
    permission_classes = [IsAuthenticated]

3. 在 users/ 下创建 urls.py 模块,编写如下路由:

#! /usr/bin/env python
# -*- coding: utf-8 -*-
# @Time : 2023/2/8 21:25
# E-mail:117220100@qq.com
# @Author : 心蓝
from django.urls import path

from rest_framework.routers import DefaultRouter

from . import views
router = DefaultRouter()
router.register('users', views.UserViewSet)

urlpatterns = [
    path('users/login/', views.LoginView.as_view(), name='login'),
    path('users/token/refresh/', views.TokenRefreshView.as_view(), name='token-refresh'),
]

urlpatterns += router.urls

4、在根路由中包含 users.urls

注意:根路由需要配置path('drf/', include('rest_framework.urls')),因为,如果不配置这个路由的话,那么在页面中不能进行登出操作

1695436736230-eeb391ba-b819-4ea7-9507-fcf1e5397797.png

from django.contrib import admin
from django.urls import path, include


urlpatterns = [
    path('admin/', admin.site.urls),
    path('drf/', include('rest_framework.urls')),
    path('', include('users.urls'))
]

三、simple-jwt 配置

Simple JWT的一些行为可以通过settings.py中的设置变量来定制: 

默认设置如下:

from datetime import timedelta

...

SIMPLE_JWT = {
    'ACCESS_TOKEN_LIFETIME': timedelta(minutes=5),  # token过期时间

    'REFRESH_TOKEN_LIFETIME': timedelta(days=1),   # 刷新token过期时间

    'ROTATE_REFRESH_TOKENS': False,    # 设置为true时,每次刷新token时都会更新refreshtoken的过期时间


   'BLACKLIST_AFTER_ROTATION': True,  # 当设置为True时,会在每次刷新token后把刷新token添加
进黑名单(ROTATE_REFRESH_TOKENS设置为True,并且起用了黑名单)

    'UPDATE_LAST_LOGIN': False, # 是否更新最后一次登录时间

    'ALGORITHM': 'HS256',  # 令牌的签名算法

    'SIGNING_KEY': settings.SECRET_KEY,  # 签名秘钥

    'VERIFYING_KEY': None,  # 验证秘钥 如果ALGORITHM设置了哈希密码算法,VERIFYING_KEY会被忽
略,SIGNING_KEY会被使用。如果ALGORITHM设置了一个RSA算法,VERIFYING_KEY必须设置为一个RSA公钥

    'AUDIENCE': None,  # aud字段声明,设置为None则解码的payload中不包含aud字段

    'ISSUER': None, # 发行人 iss字段,设置为None则解码的payload中不包含

    'JWK_URL': None, # JWK_URL用于动态解析验证令牌签名所需的公钥。

    'LEEWAY': 0, # Leeway是用来给过期时间留出一些空间的。这可以是一个以秒为单位的整数,也可以是

datetime.timedelta。

    'AUTH_HEADER_TYPES': ('Bearer',), # 需要身份验证的视图将接受的授权头类型。

    'AUTH_HEADER_NAME': 'HTTP_AUTHORIZATION', # 用于身份验证的授权头名称。HTTP_xxxx 请求头
则为xxxx

    'USER_ID_FIELD': 'id',  # 用户识别字段在数据中对应的字段

    'USER_ID_CLAIM': 'user_id', # 用户识别字段在payload中的字段名,默认user_id

    'USER_AUTHENTICATION_RULE': 

'rest_framework_simplejwt.authentication.default_user_authentication_rule', # 用户校验
规则

    'AUTH_TOKEN_CLASSES': ('rest_framework_simplejwt.tokens.AccessToken',),  # 令牌生
成类

    'TOKEN_TYPE_CLAIM': 'token_type', # 令牌类型字段名

    'JTI_CLAIM': 'jti', # 令牌标识符字段名

    'SLIDING_TOKEN_REFRESH_EXP_CLAIM': 'refresh_exp', # 用于存储滑动令牌刷新周期的过期时间
的声明名称。

    'SLIDING_TOKEN_LIFETIME': timedelta(minutes=5),  # 滑动token的有效时间

    'SLIDING_TOKEN_REFRESH_LIFETIME': timedelta(days=1), # 滑动刷新token的有效

}

配置说明详见官方文档

我们项目中仅配置两项:

 # settings.py

from datetime import timedelta

...

SIMPLE_JWT = {
    'ACCESS_TOKEN_LIFETIME': timedelta(days=1),  # 便于开发设置token过期时间1天

    'REFRESH_TOKEN_LIFETIME': timedelta(days=1),
}

四、鉴权

  • 需要鉴权的接口
    • 除注册,登录接口外,其他接口均需要权限才能访问 
  • 鉴权类型
    • JWT 
  • 鉴权方式
    • 从登录接口响应数据中获取token,以 Authorization 为请求头的key, Bearer token 作为value。 
    • Bearer 为前缀,与token值之间有一个空格,例如:
Authorization: Bearer 
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ0b2tlbiI6ImFjY2VzcyIsImV4cCI6MTYxNDY4ODU2N
SwianRpIjoiYmE4MjFiY2YzODJiNGEyMThiNTlhYWFkZmQ1YjFkYzYiLCJ1c2VyX2lkIjoxfQ.F2EvMh2a
nxtpVRIxwhu1PHbLmryAAvglZ9c1AogDU9s
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值