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

认证分类

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

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

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

表设计

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

 

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

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

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

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

这个是django的表

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

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

权限表分析注意事项

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

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

 

JWT

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

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

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

所以有了第二种 JWT

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

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

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

jwt缺点

一旦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