django实现JWT

json web token的结构

jwt的结构由三个部分组成:

  • Header
  • Payload
  • Signature

header头的格式如下

        headers = {
        #typ 属性表示令牌类型,这里就是 JWT。
            'typ': ' jwt',		
        # alg 属性表示签名所使用的算法,JWT 签名默认的算法为 HMAC SHA256 , alg 属性值 HS256 就是 HMAC SHA256 算法
            'alg': 'HS256'
        }

Payload的格式

#常用格式
payload = {
	iss:jwt的签发者/发行人;
	
	sub:主题;
	
	aud:接收方;
	
	exp:jwt过期时间;
	
	nbf:jwt生效时间;
	
	iat:签发时间
	
	jti:jwt唯一身份标识,可以避免重放攻击
}
#也可以不必遵循,例:
payload = {
    'userid': userid,        #用户表id
    'user_code': username    #用户名
}

Signature格式

#这是对前边header和payload进行签名,以后在发送/接收消息时,如果在数据被更改,则这段token值会变化,可以在每次传送数据时,判断该token是否被修改,由此判断数据是否安全
token = jwt.encode(payload=payload, key=salt, algorithm='HS256', headers=headers).decode('utf-8')
#生成的token为xxxxxx.yyyyyy.zzzzzz格式

**

场景:

**
Authorization (授权) : 用户登录发送请求,每个请求都将包含JWT,允许用户访问该令牌允许的路由、服务和资源。单点登录是现在广泛使用的JWT的一个特性,因为它的开销很小,并且可以轻松地跨域使用。
Information Exchange (信息交换) : 对于安全的在各方之间传输信息而言,JSON Web Tokens无疑是一种很好的方式。因为JWT可以被签名,例如,用公钥/私钥对,你可以确定发送人就是它们所说的那个人。另外,由于签名是使用头和有效负载计算的,您还可以验证内容没有被篡改

例如前端发送一个授权登陆请求

**

后端代码

**

from rest_framework.generics import ListAPIView
from rest_framework.response import Response
from dadaoapi.apps.home import models
from dadaoapi.settings import constant
import jwt
#dev是配置文件
from dadaoapi.settings import dev
import requests
from dadaoapi.apps.home import serializers
import json
import random       #随机生成字符串
import string
class Getopenid():
    """获取微信的openid"""
    def getopenid(self, js_code, *args, **kwargs):
        url = "https://api.weixin.qq.com/sns/jscode2session"        #请求微信服务器发送openid
        app_id = "-----------"                           #填上自己小程序的APPID
        app_secret = "--------------------------"        #填上自己小程序的app_secret
        #拼接url
        get_url = url + "?appid=" + app_id + "&secret=" + app_secret + "&js_code=" + js_code + "&grant_type=authorization_code"
        ret = requests.get(get_url)
        openid = ret.json()['openid']
        secret = ret.json()['session_key']
        return (openid, secret)

# 前端发送code获取openid并发送jwt
class GetOpenId(ListAPIView):
    """注册用户信息并发送jwt"""
    authentication_classes = []                 #登陆界面不进行authentication认证
    def post(self, request, *args, **kwargs):
        params = request.data
        js_code = params.get('jscode')         #获取到前端发送的code
        nickname = params.get('nickname')
        city = params.get('city')
        gender = params.get('gender')
        # print(params)
        # print(js_code, nickname, city, gender)
        openid_obj = Getopenid()
        openid, secret = openid_obj.getopenid(js_code)
        # print(openid, type(openid))
        try:
            user = models.UserToken.objects.get(token=openid)            #用户已存在
        except Exception as e:
            user = None
        if user:
            pass
        else:
            """测试用例,如果用户已经注册则不创建用户,否则随机创建用户名"""
            usertoken = models.UserToken.objects.create(token=openid)
            # string.digits = 0123456789
            # string.ascii_letters = 26个小写字母,26个大写字母
            str_list = random.sample(string.digits + string.ascii_letters + '_' + '!' + '#' + '$' + '*', 10)  # 随机生成字符串
            random_str = ''.join(str_list)
            name = 'dd_' + random_str  # 随机生成字符串
            name_login = models.UserTable.objects.filter(user_code=name)
            print(name_login)
            print(456)
            if name_login:
                while not name_login:
                    str_list = random.sample(string.digits + string.ascii_letters + '_' + '!' + '#' + '$' + '*',
                                             10)  # 随机生成字符串
                    random_str = ''.join(str_list)
                    name = 'dd_' + random_str  # 随机生成字符串
                    name_login = models.UserTable.objects.filter(user_code=name)
                models.UserTable.objects.create(
                    user_id=usertoken, user_code=name, nickname=nickname, gender=gender, city=city
                )
            else:
                models.UserTable.objects.create(
                    user_id=usertoken, user_code=name, nickname=nickname, gender=gender, city=city
                )
            print(user)
        #进行jwt,jwt需要有用户名和密码,随机生成密码,将openid作为用户名
        #构造headers
        userid = models.UserTable.objects.filter(user_id__token=openid).values('id').first()['id']           #取出用户id
        username = models.UserTable.objects.filter(user_id__token=openid).values('user_code').first()['user_code']    #取出用户名
        headers = {
            'typ': ' jwt',
            'alg': 'HS256'
        }
        #构造payload
        payload = {
            'userid': userid,        #用户表id
            'user_code': username    #用户名
        }
        
        #SECRET_KEY = '9d^4a9d=m2u(d+21ck1%&d7lj9wz7vr*x!$^!@gxszlvgq@4_2'这一段代码可在setting中设置默认加盐
        salt = dev.SECRET_KEY             #加盐
        token = jwt.encode(payload=payload, key=salt, algorithm='HS256', headers=headers).decode('utf-8')
       res = {
            'code': '1000',
            'data': None
        }
        res['data'] = token
        return Response(res)

**

可添加认证

**

#可添加auth认证,判断数据
from rest_framework.authentication import BaseAuthentication
import jwt
from jwt import exceptions
from dadaoapi.settings import dev
from rest_framework.response import Response
from rest_framework.exceptions import AuthenticationFailed          #导入drf报错的包
class JwtQueryAuthentication(BaseAuthentication):

    def authenticate(self, request):
        token = request.META.get('HTTP_TOKEN')
        salt = dev.SECRET_KEY
        payload = None
        msg = None
        print("经过这里")
        try:
            payload = jwt.decode(token, salt, True)
        except exceptions.ExpiredSignatureError:
            raise AuthenticationFailed({'code': 2001,'error': "token已失效"})
        except jwt.DecodeError:
            raise AuthenticationFailed({'code': 2002, 'error': "token认证失败"})
        except jwt.InvalidTokenError:
            raise AuthenticationFailed({'code': 2003, 'error': "非法的token"})
        if not payload:
            return Response({'code': 1002, 'error': msg})
        print(payload['nickname'], payload['userid'])
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值