drf自定义jwt实现登陆

简介: 简单使用

django自带的jwt认证经常会满足不了我们的需求,因此我们往往要对其进行重写才能应用。当我们有多个用户类时,我们应该怎么办呢?我的想法是分别写认证方法,然后局部认证。
首先我们看下模型类的定义。由于项目的需要,我设置两个模型类,
学生与教师。

模型类定义

学生
class Student(models.Model):

stu_id = models.AutoField(verbose_name='学生编号', primary_key=True)
stu_email = models.EmailField(verbose_name='邮箱')
stu_name = models.CharField(verbose_name='姓名', max_length=32)
sex_choice = (
    ('女性', '女'),
    ('男性', '男'),
)
stu_sex = models.SmallIntegerField(verbose_name='性别', choices=sex_choice, default=1)
class_id = models.IntegerField(verbose_name='班级编号',)
grade_id = models.IntegerField(verbose_name='年级编号',)
head_img = models.CharField(max_length=255,verbose_name="头像")
stu_password = models.CharField(verbose_name='密码', max_length=64)
stu_create_time = models.DateField(verbose_name='创建时间', auto_now_add=True)
stu_update_time = models.DateField(verbose_name='更新时间', auto_now=True)
is_delete = models.BooleanField(default=False, verbose_name='是否被删除')

class Meta:
    db_table = 'Student'
    verbose_name = '学生表'
    verbose_name_plural = verbose_name

教师
class Teacher(models.Model):

tea_id = models.AutoField(verbose_name='教师编号', primary_key=True)
tea_name = models.CharField(verbose_name='姓名', max_length=32)
tea_sex = models.CharField(verbose_name='性别', max_length=20)
tea_email = models.EmailField(verbose_name='邮箱')
tea_password = models.CharField(verbose_name='密码', max_length=64)
role = models.CharField(verbose_name='角色', max_length=20,default="教师")
tea_create_time = models.DateField(verbose_name='创建时间', auto_now_add=True)
tea_update_time = models.DateField(verbose_name='更新时间', auto_now=True)
is_delete = models.BooleanField(default=False, verbose_name='是否删除')
head_img = models.CharField(verbose_name='头像',max_length=1024,default="https://image.so.com/view?q=%E7%94%A8%E6%88%B7%E5%A4%B4%E5%83%8F&listsrc=sobox&listsign=8a31dae9c8165262bc6bf65fda6cba65&src=360pic_strong&correct=%E7%94%A8%E6%88%B7%E5%A4%B4%E5%83%8F&ancestor=list&cmsid=2d9514bb9cb82e8d68f0516fcfd2c041&cmras=0&cn=0&gn=0&kn=0&crn=0&bxn=0&fsn=60&cuben=0&pornn=0&manun=33&adstar=0&clw=283#id=8a31dae9c8165262bc6bf65fda6cba65&currsn=0&ps=86&pc=86")

class Meta:
    db_table = 'Teacher'
    verbose_name = '教师表'
    verbose_name_plural = verbose_name

登录

class LoginView(APIView):

authentication_classes = []  # 取消全局认证

def post(self, request, *args, **kwargs):
    tea_email = request.data.get('tea_email')
    tea_pwd = request.data.get('tea_password')
    tea_pwd=md5(tea_pwd)
    user_obj = Teacher.objects.filter(tea_email=tea_email, tea_password=tea_pwd).first()
    if not user_obj:
        return Response({'code': 0, 'error': '用户名或密码错误'})
    payload = {
            'tea_id': user_obj.tea_id,  # 自定义用户ID
            'tea_name': user_obj.tea_name,  # 自定义用户名
            'exp': datetime.datetime.utcnow() + datetime.timedelta(minutes=100),  # 设置超时时间,1min
            "role":user_obj.role
        }
    jwt_token = create_token(payload=payload)
    return Response({'code': 1, 'token': jwt_token,})

class StuLoginView(APIView):

authentication_classes = []  # 取消全局认证

def post(self, request, *args, **kwargs):
    stu_email = request.data.get('stu_email')
    stu_pwd = request.data.get('stu_password')
    stu_pwd=md5(stu_pwd)
    user_obj = Student.objects.filter(stu_email=stu_email, stu_password=stu_pwd).first()
    if not user_obj:
        return Response({'code': 0, 'error': '用户名或密码错误'})
    payload = {
            'stu_id': user_obj.stu_id,  # 自定义用户ID
            'stu_name': user_obj.stu_name,  # 自定义用户名
            'exp': datetime.datetime.utcnow() + datetime.timedelta(minutes=10),  # 设置超时时间,1min
            "role": user_obj.role
        }
    jwt_token = create_token(payload=payload)
    return Response({'code': 1, 'token': jwt_token})

jwt认证

class JWTQueryParamsAuthentication(BaseAuthentication):

def authenticate(self, request):
    token = request.query_params.get('token')
    if not token:
        raise AuthenticationFailed({"code": 401, "error": "登录成功后才能访问"})
    # 切割
    # 解密payload,判断是否过期
    # 验证第三段的合法性
    import jwt
    salt = settings.SECRET_KEY
    try:
        # 从token中获取payload【不校验合法性】
        # unverified_payload = jwt.decode(token, None, False)
        # print(unverified_payload)
        # 从token中获取payload【校验合法性】
        payload = jwt.decode(jwt=token, key=salt, algorithms=["HS256"])
        return (payload,token)
    except jwt.exceptions.ExpiredSignatureError:
        error = "token已失效"
        raise AuthenticationFailed({"code": 401, "error": error})
    except jwt.exceptions.DecodeError:
        error = "token已认证失败"
        raise AuthenticationFailed({"code": 401, "error": error})
    except jwt.exceptions.InvalidTokenError:
        error = "非法的token"
        raise AuthenticationFailed({"code": 401, "error": error})

def create_token(payload):

salt = settings.SECRET_KEY
# 构造Header,默认如下
headers = {
    'typ': 'jwt',
    'alg': 'HS256'
}
jwt_token = jwt.encode(headers=headers, payload=payload, key=salt, algorithm='HS256')
return jwt_token

相关文章
|
19天前
|
JSON 安全 关系型数据库
SpringCloud Gateway 实现自定义全局过滤器 + JWT权限验证
SpringCloud Gateway 实现自定义全局过滤器 + JWT权限验证
|
8月前
通过jwt基于token实现登陆认证通过jwt基于token实现登陆认证
通过jwt基于token实现登陆认证通过jwt基于token实现登陆认证
139 0
|
8月前
|
缓存 Java
Jwt使用Aop方式自定义权限注解认证
使用Aop前置通知方式, 在控制层上使用指定切面注解, 并赋予注解参数为访问接口所需角色权限代码, 进行身份认证和权限校验
56 0
|
4月前
通过jwt基于token实现登陆认证通过jwt基于token实现登陆认证
通过jwt基于token实现登陆认证通过jwt基于token实现登陆认证
20 0
|
6月前
|
存储 NoSQL Java
SpringBoot自定义实现类似jwt权限验证效果
SpringBoot自定义实现类似jwt权限验证效果
49 0
|
8月前
|
存储 JSON 算法
SpringBoot 整合JWT实现基于自定义注解的-登录请求验证拦截(保姆级教学,附:源码)1
SpringBoot 整合JWT实现基于自定义注解的-登录请求验证拦截
245 0
|
10月前
|
小程序 前端开发 Java
java如何利用JWT和注解,自定义参数的方式优雅实现小程序用户Id管理
在我们的开发项目中,经常需要用到用户ID,比如在小程序商城系统中,我们将商品加入购物车,这时前端就需要发送请求,携带上用户的ID。基本上很多种请求操作都需要携带用户ID,如果每个请求都需要我们往data中添加id的话,那样需要写很多重复代码,并且代码也不美观;所以我们可以利用JWT跟注解的方式来实现;
161 0
|
中间件 PHP
JWT详解 3 Laravel JWT自定义错误返回
JWT详解 3 Laravel JWT自定义错误返回
266 0
|
前端开发
前端:vue3+ts,后端:koa2+jwt,实现登陆功能(后端部分下篇)
前端:vue3+ts,后端:koa2+jwt,实现登陆功能(后端部分下篇)
|
监控 前端开发 数据可视化
前端:vue3+ts,后端:koa2+jwt,实现登陆功能(后端部分上篇)
前端:vue3+ts,后端:koa2+jwt,实现登陆功能(后端部分上篇)