from django.conf import settings
from jwt import exceptions
from rest_framework.authentication import BaseAuthentication
from rest_framework.exceptions import AuthenticationFailed
#生成token
#传入payload和过期时间
def creat_token(payload,exp = 1):
salt = settings.SECRET_KEY
#构造header(一般固定的,不用改)
headers = {
"type":"jwt",
"alg":"HS256"
}
#设置超时时间
payload["exp"] = datetime.datetime.utcnow() + datetime.timedelta(days=exp)
token = jwt.encode(payload,salt,"HS256",headers)
return token
#认证token
class JwtUserAuthentication(BaseAuthentication):
#继承于BaseAuthentication时需要重写authenticate这个方法
def authenticate(self, request):
#jwt处理获取用户传过来的token的步骤
#1.切割(分为三段字符串
# 2.解密第二段/判断过期时间
#3.验证第三段合法性
token = request.query_params.get("token")
salt = settings.SECRET_KEY
try:
payload = jwt.decode(token,salt,"HS256")
except exceptions.ExpiredSignatureError:
raise AuthenticationFailed({"code": 1001, 'msg':"token已失效"})
except jwt.DecodeError:
raise AuthenticationFailed({"code": 1001, 'msg': "token认证失败"})
except jwt.InvalidTokenError:
raise AuthenticationFailed({"code": 1001, 'msg': "非法的token"})
#三种操作
#1.抛出异常,后续不再执行
#2.return一个元祖(,),认证通过,在视图中如果调用request.user就是元祖的第一个值.request.auth是元祖的第二个值
#3.None
return (payload,token)
from rest_framework.views import APIView
from rest_framework.response import Response
from .models import User
from login.extensions.auth import JwtUserAuthentication,creat_token
class LoginView(APIView):
'''用户登录'''
def post(self,request):
user = request.data.get("username")
pwd = request.data.get("password")
user_object = User.objects.filter(username=user,password=pwd).first()
if not user_object:
return Response({"code":1001,"msg":"用户名或密码错误"})
token = creat_token({"id":user_object.id,"name":user_object.username})
return Response({"code":200,"data":token})
class UserInfoView(APIView):
'''获取用户信息接口'''
#加入这个配置相当于中间件的作用,在执行这个视图之前会先执行JwtUserAuthentication的方法.所以可以把认证的方法写在JwtUserAuthentication类里
authentication_classes = [JwtUserAuthentication, ]
def get(self,request):
return Response(request.user)
django获取参数的方式
- request.query_params.get("token") 获取get方法传参
- request.data.get("token") 获取post方式传参
- request.META.get('HTTP_TOKEN') 获取header里面的参数(token:***)
网友评论