JWT实现过程及应用
# 用户登录,返回给客户端token(服务端不保存),用户带着token,服务端拿到token再校验; 1,提交用户名和密码给服务端,如果登陆成功,jwt会创建一个token,并返回; 第一段:header,内部包含 (算法/token类型) { "typ": "JWT", # 声明类型为jwt "alg": "HS256" # 声明签名算法为SHA256 } # json转化字符串做base64url加密,可反解 第二段:payload,包含(标准中注册的声明、公共声明、私有声明(用户信息)) { # 私有声名 “id”: “12”, “name”: “bajie″, “exp”: 60 # 超时时间 } # 公共声明:公共的声明可以添加任何的信息,一般添加用户的相关信息或其他业务需要的必要信息. """ 注册的声明 iss: jwt签发者 sub: jwt所面向的用户 aud: 接收jwt的一方 exp: jwt的过期时间,这个过期时间必须要大于签发时间 nbf: 定义在什么时间之前,该jwt都是不可用的. iat: jwt的签发时间 jti: jwt的唯一身份标识,主要用来作为一次性token,从而回避重放攻击。 """ # json转化字符串做base64url加密,可反解 第三段: 1,将第一段和第二段的密文拼接 2,HS256加密 + 加盐 3,对HS256加密后的密文再用 base64url 加密 2,用户访问,需要携带token,后端进行校验 1,获取token 2,切割,对第二段解密,获取payload信息,检测是否超时 3,把第一段和第二段的密文拼接,再次执行HS256加密 + 加盐 得到 密文 4,密文 == token 匹配 (如果修改超时时间 则不通过)
安装: pip install pyjwt import jwt import datetime from rest_framework.views import APIView from rest_framework.response import Response from jwt import exceptions from api import models class LoginAPIview(APIView): def get(self, request, *args, **kwargs): # 盐 sail = "sadjmasklfn63a5s62dwa@ddas/352asdfa" """ 1,获取token 2,切割,对第二段解密,获取payload信息,检测是否超时 3,把第一段和第二段的密文拼接,再次执行HS256加密 + 加盐 得到 密文 4,密文 == token 匹配 (如果修改超时时间 则不通过) """ token = request.query_params.get("token") verified_payload = None msg = '' try: # 反解出来的第二段数据 verified_payload = jwt.decode(token, sail, True) except exceptions.ExpiredSignatureError: # 超时 msg = "token失效" except jwt.DecodeError: msg = "token认证失败" except jwt.InvalidTokenError: msg = "非法token" if not verified_payload: return Response({'code': '登录失败', "error": msg}) # print(verified_payload["id"],verified_payload["username"]) return Response({"ok": "登陆成功"}) def post(self, request, *args, **kwargs): user = request.data.get('username') pswd = request.data.get('password') obj = models.UserInfo.objects.filter(username=user, password=pswd).first() if obj: # 盐 sail = "sadjmasklfn63a5s62dwa@ddas/352asdfa" # 构造 第一段: header, 内部包含(算法 / token类型) 默认 headers = { "typ": "JWT", # 声明类型为jwt "alg": "HS256" # 声明签名算法为SHA256 } # 第二段: payload, 包含(标准中注册的声明、公共声明、私有声明(用户信息)) payload = { # 私有声名 'id': obj.id, 'username': obj.username, 'exp': datetime.datetime.utcnow() + datetime.timedelta(minutes=1) # 超时时间1分钟 } res_token = jwt.encode(headers=headers, payload=payload, key=sail, algorithm='HS256').decode('utf-8') return Response({"msg": "登录成功", "token": res_token}) return Response("0")