JWT

Json web token (JWT), 是为了在网络应用环境间传递声明而执行的一种基于JSON的开放标准((RFC 7519).该token被设计为紧凑且安全的,特别适用于分布式站点的单点登录(SSO)场景。JWT的声明一般被用来在身份提供者和服务提供者间传递被认证的用户身份信息,以便于从资源服务器获取资源,也可以增加一些额外的其它业务逻辑所必须的声明信息,该token也可直接被用于认证,也可被加密

JWT的构成:

  • 三段式:
    - header:一般放公司信息,加密方式 (用处不大)
    - payload:用户信息: user_id,user_name,email,expire
    - signature:第一部分和第二部加密得到的
  • 通过base64转码
pip install djangorestframework-jwt

签发

# 在路由中配置
from rest_framework_jwt.views import obtain_jwt_token
urlpatterns = [
    path('login/', obtain_jwt_token),  # 登录接口好了,可以签发token,依赖了auth的user表
]

认证

from rest_framework_jwt.authentication import JSONWebTokenAuthentication  # drf_jwt内置的认证类
from rest_framework.permissions import IsAuthenticated 
class BookView(APIView):
    # 使用drf_jwt内置的认证,必须加这两个
    authentication_classes = [JSONWebTokenAuthentication, ]
    permission_classes = [IsAuthenticated]

自定义token签发认证

from rest_framework.response import Response
from .models import UserInfo
from rest_framework_jwt.settings import api_settings

jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER
jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER


class LoginView(APIView):
    def post(self, request):
        username = request.data.get('username')
        password = request.data.get('password')
        user = UserInfo.objects.filter(username=username, password=password).first()
        if user:  # 用户名和密码正确,登录成功,签发token
            payload = jwt_payload_handler(user)
            token = jwt_encode_handler(payload)
            return Response({'code': '100', 'msg': '登录成功', 'token': token, 'usrename': user.username})
        else:
            return Response({'code': '101', 'msg': '用户名或密码错误'})
        
        
        
        
from rest_framework.authentication import BaseAuthentication
from rest_framework import exceptions
import jwt
from .models import UserInfo
from rest_framework_jwt.settings import api_settings
jwt_decode_handler = api_settings.JWT_DECODE_HANDLER
class JwtAuthentication(BaseAuthentication):
    def authenticate(self, request):
        # 取出前端传入的token串
        token=request.META.get('HTTP_TOKEN')
        # 通过token获得payload
        try:
            payload = jwt_decode_handler(token) # 通过token串获得payload,验签(是否被篡改),检查过期时间
        # except Exception:
        #     raise exceptions.AuthenticationFailed('token认证失败')
        except jwt.ExpiredSignature:
            msg = '签名过期'
            raise exceptions.AuthenticationFailed(msg)
        except jwt.DecodeError:
            msg ='解码错误'
            raise exceptions.AuthenticationFailed(msg)
        except jwt.InvalidTokenError:
            raise exceptions.AuthenticationFailed()
        # 通过payload获得当前用户(自己的表,自己拿)
        # user=UserInfo.objects.filter(pk=payload['user_id']).first()
        
        
        # 稍微优化一下,不是每次都取查询当前登录用户
        # user={'id':payload['user_id'],'username':payload['username']}
        user=UserInfo(id=payload['user_id'],username=payload['username'])
        # 返回当前用户
        return user,token       
posted @ 2022-01-24 22:38  下个ID见  阅读(22)  评论(0)    收藏  举报