Django: 使用django-rest-framework-jwt时自定义user表(且未继承auth.user表)

django_rest_frameworker jwt 是基于django自带的认证系统(库中的auth_user表)来实现的,

也就是说我们的用户表(user)需要直接继承django自带的AbstractUser表,在此基础上添加字段。

网上大部分的文章也是默认这么做的。

由于事先已经自定义的user表,而且没有继承 AbstractUser,所以需要重写一些方法来使用我们自建的user表数据。

from rest_framework_jwt.utils import jwt_decode_handler
import jwt
from rest_framework.exceptions import AuthenticationFailed
from rest_framework_jwt.authentication import BaseJSONWebTokenAuthentication
from account.models import User


class JwtAuthentication(BaseJSONWebTokenAuthentication):
    """
    当User表为自定义的表,而且没有继承自django自带的auth.User表时,需要重写验证方法:authenticate
    """
    def authenticate(self, request):
        token = request.META.get('HTTP_Authorization'.upper())
        print(token)
        try:
            payload = jwt_decode_handler(token)
        except jwt.ExpiredSignature:
            raise AuthenticationFailed('亲,token放太久了,都过期了,快去重新获取吧!')
        except jwt.DecodeError:
            raise AuthenticationFailed('token为空或者解码错误')
        except jwt.InvalidTokenError:
            raise AuthenticationFailed('不合法的token')
        # 得到的user对象,应该是自己user表的user对象
        # print(payload)
        # payload内容:{'user_id': 1, 'username': '66559575', 'exp': 1620538525, 'email': '66559575@cho.cn'}
        user = User.objects.get(id=payload['user_id'])
        # user = payload
        return user, token

其中的关键就是获取user实例,user= User.objects.get(id=payload['user_id'])

在settings.py中做如下配置,如果配置了则表示全局认证,所有接口都需要token

REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': [
        # 全局配置使用自定义的token认证
        'common.JWTAuthentication.JwtAuthentication',
        # 使用JWT Token认证
        'rest_framework_jwt.authentication.JSONWebTokenAuthentication',
        # Basic类型的认证(账号和密码)
        'rest_framework.authentication.SessionAuthentication',
        # Session会话认证
        'rest_framework.authentication.BasicAuthentication',
    ],
}

JWT_AUTH = {
    # token过期时间
    'JWT_EXPIRATION_DELTA': datetime.timedelta(hours=1),  # seconds=300 5分钟
    # token前缀
    # 'JWT_AUTH_HEADER_PREFIX': 'JWT',
}

如果没有配置全局应用,只需要控制某视图的权限,

则在视图类中添加 authentication_classes = [JwtAuthentication],指定上面自定义的认证类

class ListSubSys(generics.ListAPIView):
    """
    获取子系统列表
    """
    queryset = SubSys.objects.all()
    serializer_class = SubSysSerializers
    # 使用自定义分页
    pagination_class = CustomPagination
    # 模糊匹配查询
    filterset_class = sub_sys_filter.SubSysFilter
    # JWT认证,使用自定义的JwtAuthentication,继承自JSONWebTokenAuthentication
    authentication_classes = [JwtAuthentication]
    # permission_classes = [IsAuthenticated]

 认证功能局部使用和全局使用

# 1 全局使用(所有接口,都需要登录才能访问)
    -在配置文件中
     REST_FRAMEWORK = {
        "DEFAULT_AUTHENTICATION_CLASSES": ["common.JWTAuthentication.JWTAuthentication", ]
        }
#2 局部使用
    -在想局部使用的视图类上写上下面这条
    authentication_classes = [JwtAuthentication] 

#3 局部禁用 -在想禁用的视图类上
authentication_classes
= []

 

posted @ 2021-05-10 15:12  秋寻草  阅读(1166)  评论(0编辑  收藏  举报