在前后端分离项目中,用到最常用的认证方式就是JWT方式了,关于jwt的介绍我我就不讲了,网上一搜一大堆,下面直接进入正题
前提:
- 创建相关用户数据模型
- 安装djangorestframework
- 序列化user模型
手写JWT方式认证
关于手写jwt,其实就是利用pyjwt
生成token,通过修改rest_framework.authentication
的BaseAuthentication
方法完成,
安装pyjwt
pip install pyjwt
在app中创建一个authentications.py
文件,修改rest_framework.authentication
的BaseAuthentication
方法
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
@author: 小羊驼
@contact: wouldmissyou@163.com
@time: 2020/8/14 下午1:12
@file: authentications.py
@desc:
"""
import jwt
import time
from django.conf import settings
from rest_framework.authentication import BaseAuthentication,get_authorization_header
from rest_framework import exceptions
from django.contrib.auth import get_user_model
from jwt.exceptions import ExpiredSignatureError
User = get_user_model()
def generate_jwt(user):
expire_time = time.time() + 60*60*24*7
return jwt.encode({"userid":user.pk,"exp":expire_time},key=settings.SECRET_KEY).decode('utf-8')
class JWTAuthentication(BaseAuthentication):
keyword = 'JWT'
def authenticate(self, request):
auth = get_authorization_header(request).split()
if not auth or auth[0].lower() != self.keyword.lower().encode():
return None
if len(auth) == 1:
msg = "不可用的JWT请求头!"
raise exceptions.AuthenticationFailed(msg)
elif len(auth) > 2:
msg = '不可用的JWT请求头!JWT Token中间不应该有空格!'
raise exceptions.AuthenticationFailed(msg)
try:
jwt_token = auth[1]
jwt_info = jwt.decode(jwt_token,settings.SECRET_KEY)
userid = jwt_info.get('userid')
try:
# 绑定当前user到request对象上
user = User.objects.get(pk=userid)
return user, jwt_token
except:
msg = '用户不存在!'
raise exceptions.AuthenticationFailed(msg)
except ExpiredSignatureError:
msg = "JWT Token已过期!"
raise exceptions.AuthenticationFailed(msg)
在视图中直接使用我们创建的这个方法
#view.py
rom rest_framework.views import APIView
from users.serializers import UserSerializer
from rest_framework.authtoken.serializers import AuthTokenSerializer
from django.contrib.auth import get_user_model
User = get_user_model()
from django.utils.timezone import now
from users.authentications import generate_jwt
from rest_framework.response import Response
from rest_framework_jwt.views import api_settings
class LoginView(APIView):
def post(self, request):
serializer = AuthTokenSerializer(data=request.data)
if serializer.is_valid():
user = serializer.validated_data.get('user')
user.last_login = now()
user.save()
token = generate_jwt(user)
user_serializer = UserSerializer(user)
print(user)
return Response({"token": token, "user":user_serializer.data})
else:
return Response({'message': "用户名或密码错误"})
最后urls.py中加上就行了
使用djangorestframework-jwt
安装
pip install djangorestframework-jwt
setting.py中配置相关
REST_FRAMEWORK = {
# 'DEFAULT_PERMISSION_CLASSES': (
# 'rest_framework.permissions.IsAuthenticated',
# ),
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework_jwt.authentication.JSONWebTokenAuthentication',
'rest_framework.authentication.SessionAuthentication',
'rest_framework.authentication.BasicAuthentication',
),
}
在视图中我们直接使用手动生成令牌
from rest_framework.views import APIView
from users.serializers import UserSerializer
from rest_framework.authtoken.serializers import AuthTokenSerializer
from django.contrib.auth import get_user_model
User = get_user_model()
from django.utils.timezone import now
from users.authentications import generate_jwt
from rest_framework.response import Response
from rest_framework_jwt.views import api_settings
from rest_framework_jwt.authentication import JSONWebTokenAuthentication
class LoginView(APIView):
def post(self, request):
serializer = AuthTokenSerializer(data=request.data)
if serializer.is_valid():
user = serializer.validated_data.get('user')
user.last_login = now()
user.save()
# token = generate_jwt(user)
jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER
jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER
payload = jwt_payload_handler(user)
token = jwt_encode_handler(payload)
user_serializer = UserSerializer(user)
print(user)
return Response({"token": token, "user":user_serializer.data})
else:
return Response({'message': "用户名或密码错误"})
OK了 以后前端访问数据,直接携带token就行了
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END
- 最新
- 最热
只看作者