drf-jwt

jwt

一 jwt基本认知

为什么要用jwt?

避免了大量io,所以大大降低数据库的压力以及后端的压力

见图:

安装drf-jwt

具体token串(了解)

"""
jwt:json web tokens 采用json格式在web上传输的 认证字符串

jwt字符串:头.载荷.签名

头:公司基本信息、项目组基本信息、常规加密算法名
载荷:用户信息、过期时间
签名:头、载荷、秘钥

{头信息字典,采用base64加密算法}.{载荷信息字典,采用base64加密算法}.{头加密串、载荷加密串、服务器秘钥,采用hs256加密算法}

base64是可逆加密
hash256是不可逆加密
"""

加密解密没啥好说的,但是如果hash成功了第三段的话,那么也就意味着这个加密串是我发的,因为用的hash算法是同一个,那么服务器也是统一个。

# 大概思路
#1 首先制作token
把第一段和第二段base64加密出来,然后把第一段和第二段加密成了第三段。
#2 验证token
首先拿着第一段和第二段hash一下,看看是否是第三段,然后base64解密第一段。

二 具体使用

urls.py

from django.conf.urls import url,include
from rest_framework_jwt.views import ObtainJSONWebToken, obtain_jwt_token
from . import views


urlpatterns = [
    # 1 直接可以post访问得到 token
    # 自带post方法 会自己校验 username以及password 并且设置好token进行返回
    url(r'^v2/login/$', obtain_jwt_token),

    # 2 利用源码定制token进行返回
    url(r'^v3/login/$', views.LoginJWTAPIView.as_view()),

    # 3 认证组件的使用
    url(r'^v3/cars/$', views.CarV3ModelViewSet.as_view({
        'get': 'list',
        'post': 'create'
    })),
    url(r'^v3/cars/(?P<pk>.*)/$', views.CarV3ModelViewSet.as_view({
        'get': 'retrieve',
        'put': 'update',
        'patch': 'partial_update',
        'delete': 'destroy',
    })),

]

views.py

from django.shortcuts import render

# Create your views here.

#### authors 组件小用法跟本文不大
from rest_framework.response import Response
from rest_framework.views import APIView
from django.contrib import auth
class LoginSessionAPIView(APIView):
    # 登录要禁用认证与权限
    authentication_classes = []
    permission_classes = []
    def post(self, request, *args, **kwargs):
        username = request.data.get('username')
        password = request.data.get('password')
        if not (username and password):
            return Response('信息有误')
        # user = models.User.objects.filter(username=username).first()  # type: models.User
        # user.check_password(password)
        # 直接自己就可以进行验证了
        user = auth.authenticate(request, username=username, password=password)
        if not user:
            return Response('登录失败')
        auth.login(request, user=user) #会把sessionid放进去返回
        return Response('登录成功')


# 直接drf的源码的封装token和解密token的部件使用
from . import models
import re
from my_utils.response import APIResponse
from rest_framework_jwt.serializers import jwt_encode_handler, jwt_payload_handler
class LoginJWTAPIView(APIView):
    authentication_classes = ()
    permission_classes = ()
    def post(self, request, *args, **kwargs):
        # username可能携带的不止是用户名,可能还是用户的其它唯一标识 手机号 邮箱
        username = request.data.get('username')
        password = request.data.get('password')

        # 如果username匹配上手机号正则 => 可能是手机登录
        if re.match(r'1[3-9][0-9]{9}', username):
            try:
                # 手动通过 user 签发 jwt-token
                user = models.User.objects.get(mobile=username)
            except:
                return APIResponse(1, '该手机未注册')

        # 邮箱登录 等

        # 账号登录
        else:
            try:
                # 手动通过 user 签发 jwt-token
                user = models.User.objects.get(username=username)
            except:
                return APIResponse(1, '该账号未注册')

        # 获得用户后,校验密码并签发token
        # 这个验证密码感觉是自带的 会把你的密码和数据库的密码进行对比
        # python的Django框架自带了一套加密方法: make_password(), 具体作用如下:
        # 这时候如果需要验证密码比较是否正确就需要用check_password( ),具体如下:
        if not user.check_password(password):
            return APIResponse(1, '密码错误')
        payload = jwt_payload_handler(user)
        token = jwt_encode_handler(payload)
        return APIResponse(0, 'ok', results={
            'username': user.username,
            'mobile': user.mobile,
            'token': token
        })




# 局部使用jwt认证组件
from . import serializers
from rest_framework.viewsets import ModelViewSet
from rest_framework_jwt.authentication import JSONWebTokenAuthentication
from rest_framework.permissions import IsAuthenticatedOrReadOnly
class CarV3ModelViewSet(ModelViewSet):
    # 认证组件的token格式是 在Headers里添加字段 authorization:jwt sdfj.jasdf.xxyandls
    authentication_classes = [JSONWebTokenAuthentication] # 用token确定身份 游客 or 登录用户 用request.user来确定
    permission_classes = [IsAuthenticatedOrReadOnly] # 根据身份确定权限
    queryset = models.Car.objects.filter(is_delete=False)
    serializer_class = serializers.CarModelSerializer
    def destroy(self, request, *args, **kwargs):
        obj = self.get_object()
        obj.is_delete = True
        obj.save()
        return Response('删除成功')

setting.py

# 配置自定义User表
AUTH_USER_MODEL = 'api.user'
# 配置自定义User表
AUTH_USER_MODEL = 'api.user'
# jwt配置
import datetime
JWT_AUTH = {
    'JWT_EXPIRATION_DELTA': datetime.timedelta(seconds=30000),
    'JWT_AUTH_HEADER_PREFIX': 'TOKEN', # 可以修改访问的时候具体修改 'jwt' 的内容
}

serializers.py

from rest_framework import serializers
from . import models


class UserModelSerializer(serializers.ModelSerializer):
    class Meta:
        model = models.User
        fields = ('username', 'mobile')

class CarModelSerializer(serializers.ModelSerializer):
    class Meta:
        model = models.Car
        fields = ('name',)


访问的方式

posted @ 2019-11-21 17:25  张明岩  阅读(575)  评论(0编辑  收藏  举报