前后端分离认证 认证使用JWT

认证分类

认证分为 RBAC与Auth  而我们Django就是RBAC

那么什么是RBAC呢? 就是基于角色的访问控制

而这种表设置分为 3表 5表 6表

表设计

 

 5表产生原因 多对多的原因

 

一种是用户破格拥有某种权限,不依赖身份 表

这个是django的表

对应着身份与权限以及用户的对应关系 表示哪些用户是哪个分组 哪些权限

权限表分析注意事项

因为user里面还有其他字段 需要继承,并告诉DJango 使用自己的user表

当时如果数据库迁移后 就无法再使用了 所以一定要在迁移之前进行继承AsbrUser

 

JWT

虽然认证不用去数据库校验session,但是服务器遇到登陆注册的时候 还是需要生成session并保存,也是需要io操作 

还得去校验session  所以我们就索性不去校验了

 

所以有了第二种 JWT

你给我的信息 我通过算法给你生成一个token ,你下次来请求我,你把token带上

你下次请求我的时候 带上这个token 我进行解密,如果没有问题 我就给您通过

jwt缺点

一旦JWT签发,在有效期内将会一直有效

JWT使用

#下载
pip install djangorestframework-jwt

#post请求登陆成功 返回token
from django.urls import path
from rest_framework_jwt.views import obtain_jwt_token
urlpatterns = [
    path('login/', obtain_jwt_token),
]

#使用自己的返回token方法 import datetime JWT_AUTH = { # 过期时间 'JWT_EXPIRATION_DELTA': datetime.timedelta(days=1), # 自定义认证结果:见下方序列化user和自定义response 'JWT_RESPONSE_PAYLOAD_HANDLER': 'user.utils.jwt_response_payload_handler', }

自定义返回token  (可以再自己的util模块写因为这是公共的)

from .serializers import UserModelSerializers
def jwt_response_payload_handler(token, user=None, request=None):
    return {
        'token': token,
        'user': UserModelSerializer(user).data
    }
from rest_framework import serializers
from .models import User
class UserModelSerializer(serializers.ModelSerializer):
    """轮播图序列化器"""
    class Meta:
        model = User
        fields = ["username", "mobile"]

开始认证user/authentications.py(自己创建)

import jwt
from rest_framework.exceptions import AuthenticationFailed
from rest_framework_jwt.authentication import jwt_decode_handler
from rest_framework_jwt.authentication import get_authorization_header
from rest_framework_jwt.authentication import BaseJSONWebTokenAuthentication
class JSONWebTokenAuthentication(BaseJSONWebTokenAuthentication):
        def authenticate(self, request):
            # 采用drf获取token的手段 - HTTP_AUTHORIZATION - Authorization
            token = get_authorization_header(request)
            if not token:
                raise AuthenticationFailed('Authorization 字段是必须的')
            # 可以添加反扒措施:原功能是token有前缀

            # drf-jwt认证校验算法
            try:
                payload = jwt_decode_handler(token)
            except jwt.ExpiredSignature:
                raise AuthenticationFailed('签名过期')
            except jwt.InvalidTokenError:
                raise AuthenticationFailed('非法用户')
            user = self.authenticate_credentials(payload)
            # 将认证结果丢该drf
            return user, token

全局配置 局部配置

REST_FRAMEWORK = {
    # 认证模块
    'DEFAULT_AUTHENTICATION_CLASSES': (
        'user.authentications.JSONWebTokenAuthentication',
    ),
}

# 局部禁用
authentication_classes = []

 
   

# 局部启用
from user.authentications import JSONWebTokenAuthentication
authentication_classes = [JSONWebTokenAuthentication]

 

多方式登录

配置

AUTHENTICATION_BACKENDS = ['user.utils.JWTModelBackend']
from django.contrib.auth.backends import ModelBackend
from .models import User
import re
class JWTModelBackend(ModelBackend):
    def authenticate(self, request, username=None, password=None, **kwargs):
        """
        :param request:
        :param username: 前台传入的用户名
        :param password: 前台传入的密码
        :param kwargs:
        :return:
        """
        try:
            if re.match(r'^1[3-9]\d{9}$', username):
                user = User.objects.get(mobile=username)
            elif re.match(r'.*@.*', username):
                user = User.objects.get(email=username)
            else:
                user = User.objects.get(username=username)
        except User.DoesNotExist:
            return None  # 认证失败就返回None即可,jwt就无法删除token
        # 用户存在,密码校验通过,是活着的用户 is_active字段为1
        if user and user.check_password(password) and self.user_can_authenticate(user):
            return user  # 认证通过返回用户,交给jwt生成token