美文网首页Django
djangorestframework-simplejwt简单使

djangorestframework-simplejwt简单使

作者: Hahn_z | 来源:发表于2020-03-24 10:48 被阅读0次

我为什么要使用djangorestframework-simplejwt

现在Django-rest-framework-jwt网上有许多文章
但是现在Django-rest-framework-jwt停止维护了

image.png

djangorestframework-simplejwt详细文档

安装

pip install djangorestframework_simplejwt

设置

在settings.py中

# drf配置
REST_FRAMEWORK = {
    # JWT
    'DEFAULT_AUTHENTICATION_CLASSES': (
        'rest_framework_simplejwt.authentication.JWTAuthentication',
    ),

}

# JWT配置 里面具体配置可以参考文档
SIMPLE_JWT = {
    'ACCESS_TOKEN_LIFETIME': timedelta(days=7),  # 配置过期时间
    'REFRESH_TOKEN_LIFETIME': timedelta(days=15),
}

在主目录下面的urls.py

"""pine_mountain_bridge URL Configuration

The `urlpatterns` list routes URLs to views. For more information please see:
    https://docs.djangoproject.com/en/3.0/topics/http/urls/
Examples:
Function views
    1. Add an import:  from my_app import views
    2. Add a URL to urlpatterns:  path('', views.home, name='home')
Class-based views
    1. Add an import:  from other_app.views import Home
    2. Add a URL to urlpatterns:  path('', Home.as_view(), name='home')
Including another URLconf
    1. Import the include() function: from django.urls import include, path
    2. Add a URL to urlpatterns:  path('blog/', include('blog.urls'))
"""
from django.contrib import admin
from django.urls import path
from django.conf.urls import url, include
from rest_framework.documentation import include_docs_urls
from rest_framework.routers import DefaultRouter
from django.views.static import serve



urlpatterns = [
    path('admin/', admin.site.urls),

    # rest_framework_simplejwt自带的得到token
    path('api/token/', TokenObtainPairView.as_view(), name='token_obtain_pair'),
    # 刷新JWT
    path('api/v1/token/refresh/', TokenRefreshView.as_view(), name='token_refresh'),
    # 验证token
    path('api/token/verify/', TokenVerifyView.as_view(), name='token_verify'),
]

得到token数据返回
refresh书用来刷新的
access是token

{
        "refresh": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ0b2tlbl90eXBlIjoicmVmcmVzaCIsImV4cCI6MTU4NjMxMjYyOSwianRpIjoiZWUzNTQxNmIzMDZjNDIyY2EyOWFiOGQ5NjhlNjc3ZWYiLCJ1c2VyX2lkIjoxfQ.th5AfYNsd9UK3zL9LEhnDRNrd37Ut8ucl-G9VzYlCHI",
        "access": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ0b2tlbl90eXBlIjoiYWNjZXNzIiwiZXhwIjoxNTg1NjIxNDI5LCJqdGkiOiJlYmI3ZDdmOTBlNzU0OTNkYjM4NTNiNTJkYzA0Yjk3NiIsInVzZXJfaWQiOjF9.WeoTxQ2rG0BOl9ji6KO3yfLm83kcsHV1drFDxGxAvGA",
}

刷新得到的数据

{
        "access": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ0b2tlbl90eXBlIjoiYWNjZXNzIiwiZXhwIjoxNTg1NjIxNTIyLCJqdGkiOiI4MzcyN2UwYWVhMDU0MWYyYmE1ODljOWY5NTMzYjE2OSIsInVzZXJfaWQiOjF9.NTo1YKFl9tvcCYQVmBWLz0rhRL8044qT65jbe7okeG0"
    }

自定义djangorestframework-simplejwt

在你的serializers.py

from rest_framework_simplejwt.serializers import TokenObtainPairSerializer


class MyTokenObtainPairSerializer(TokenObtainPairSerializer):

    '''
    token验证
    '''
    def validate(self, attrs):
        data = super().validate(attrs)

        refresh = self.get_token(self.user)

        data['refresh'] = str(refresh)
        data['access'] = str(refresh.access_token)
        data['username'] = self.user.username #这个是你的自定义返回的
        data['user_id'] = self.user.id #这个是你的自定义返回的

        return data


在你的views.py

from rest_framework_simplejwt.views import TokenViewBase
from rest_framework_simplejwt.serializers import TokenRefreshSerializer

from .serializers import *
from .models import *


class MyTokenObtainPairView(TokenObtainPairView):
    """
    自定义得到token username: 账号或者密码 password: 密码或者验证码
    """
    serializer_class = MyTokenObtainPairSerializer


class MyTokenRefreshView(TokenViewBase):
    """
    自定义刷新token refresh: 刷新token的元素
    """
    serializer_class = TokenRefreshSerializer

PS 记得写url。我这里就不写了

得到token

{
    "msg": "success",
    "code": 1,
    "data": {
        "refresh": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ0b2tlbl90eXBlIjoicmVmcmVzaCIsImV4cCI6MTU4NjMxMjYyOSwianRpIjoiZWUzNTQxNmIzMDZjNDIyY2EyOWFiOGQ5NjhlNjc3ZWYiLCJ1c2VyX2lkIjoxfQ.th5AfYNsd9UK3zL9LEhnDRNrd37Ut8ucl-G9VzYlCHI",
        "access": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ0b2tlbl90eXBlIjoiYWNjZXNzIiwiZXhwIjoxNTg1NjIxNDI5LCJqdGkiOiJlYmI3ZDdmOTBlNzU0OTNkYjM4NTNiNTJkYzA0Yjk3NiIsInVzZXJfaWQiOjF9.WeoTxQ2rG0BOl9ji6KO3yfLm83kcsHV1drFDxGxAvGA",
        "username": "hahn",
        "user_id": 1
    }
}

刷新token

{
    "msg": "success",
    "code": 1,
    "data": {
        "access": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ0b2tlbl90eXBlIjoiYWNjZXNzIiwiZXhwIjoxNTg1NjIxNTIyLCJqdGkiOiI4MzcyN2UwYWVhMDU0MWYyYmE1ODljOWY5NTMzYjE2OSIsInVzZXJfaWQiOjF9.NTo1YKFl9tvcCYQVmBWLz0rhRL8044qT65jbe7okeG0"
    }
}

上面自定义数据结构的传送门

接口验证

在你的views.py中

class UserViewSet(CacheResponseMixin, viewsets.ModelViewSet):
    """
    测试的Api1
    """
    permission_classes = [permissions.IsAuthenticated]  # 权限认证主要是这个
    queryset = User.objects.all()
    serializer_class = UserSerializer
    throttle_classes = []

    # 自定义分页
    pagination_class = LisPagination

错误返回

{
    "msg": "身份认证信息未提供。",
    "state": 0,
    "data": ""
}

这个token是加在请求头的Authorization
太长就截图看了

截屏2020-03-24上午10.35.52.png 截屏2020-03-24上午10.36.53.png

现在自定义token接口完成了

但是drf jwt默认验证的是username和password
突然想验证手机号码或者其他什么的只是自定义了
PS:本来想换请求数据中的key的、就是不要username、password。因为能力有限暂时不知道怎么换。看了好久源码好像是和Django user模型绑定了

在settings.py中
pine_mountain_bridge里面的utils新建CustomToken.py

# 自定义JWT校验
AUTHENTICATION_BACKENDS = (
    'pine_mountain_bridge.utils.CustomToken.CustomBackend',
)

CustomToken.py

# 自定义得到token校验

from django.contrib.auth.backends import ModelBackend
from django.db.models import Q
from rest_framework import serializers


from users.models import *


class CustomBackend(ModelBackend):
    def authenticate(self, request, username=None, password=None, **kwargs):
        # print(request.data) 参考请求的其他数据
        # print(request.data['demo']) 比如说key是demo的数据用来做你要的数据校验
        try:
            # 小编这里添加了一个手机验证,如果需要其他验证再加就ok了
            try:
                user = Users.objects.get(Q(username=username) | Q(mobile=username))
            except Exception:
                raise serializers.ValidationError({'': '账号没有注册'})

            if user.check_password(password):
                return user
            else:
                # 如果不想密码登录也可以验证码在这里写
                # 这里做验证码的操作
                raise serializers.ValidationError({'': '密码错误'})

        except Exception as e:
            raise e


返回数据

截屏2020-03-24上午10.45.40.png

jwt解码

根据token返回对于的数据
在你的serializers.py

from rest_framework_simplejwt.serializers import TokenVerifySerializer
from jwt import decode as jwt_decode

class MyTokenVerifySerializer(TokenVerifySerializer):
    """
    token验证
    """

    def validate(self, attrs):
        """
        attrs['token']: 是请求的token
        settings.SECRET_KEY: setting.py默认的key 除非在配置文件中修改了
        algorithms: 加密的方法
        """
        decoded_data = jwt_decode(attrs['token'], settings.SECRET_KEY, algorithms=["HS256"])
        return decoded_data

在views.py

from rest_framework_simplejwt.views import TokenObtainPairView, TokenViewBase
class MyTokenVerifyView(TokenViewBase):
    """
    验证token得到用户信息 token: 验证的token
    """
    serializer_class = MyTokenVerifySerializer

返回的数据
user_id就是你的用户ID

{
    "msg": "success",
    "status": 200,
    "data": {
        "token_type": "access",
        "exp": 1585710741,
        "jti": "97b42a6570d84108bf09701a60fbf5c1",
        "user_id": 1
    }
}

djangorestframework-simplejwt退出登录

JWT是不带退出内置的办法的
JWT退出登录很多方法
我这里是使用Django-redis库、用redis管理JWT的状态。用用户作为key保存token。
因为每个人的业务逻辑不一样、我就贴一些关键的代码

在setting.py

# redis配置
CACHES = {
    "default": {
        "BACKEND": "django_redis.cache.RedisCache",
        "LOCATION": "redis://127.0.0.1:6379",
        "OPTIONS": {
            "CLIENT_CLASS": "django_redis.client.DefaultClient",
            "PASSWORD": "",
        }
    }
}

# redis缓存时间
REDIS_TIMEOUT = 60*60*24*7

使用

from django.core.cache import cache

保存redis缓存

        # 设置redis缓存
        # redis_key你的key
        # token token
        # REDIS_TIMEOUT 保存的数据
        cache.set(redis_key, token, REDIS_TIMEOUT)

清除redis缓存
我这里是把value变成空了、方便我判断

        # 设置redis缓存
        # redis_key你的key
        # REDIS_TIMEOUT 保存的数据
        cache.set(redis_key,'', REDIS_TIMEOUT)

查看redis缓存

# 解码token得到user_id
decoded_data = jwt_decode(token algorithms=["HS256"])
# redis_key 你设置的redis的key
results = cache.get(redis_key)
# 判断、写自己的业务逻辑

相关文章

  • djangorestframework-simplejwt简单使

    我为什么要使用djangorestframework-simplejwt 现在Django-rest-framew...

  • 使之简单

    假如真的决定要开始练习冥想,你不必跑去告知他人,也不必谈论你进行冥想的理由或它会给你带来何种益处。事实上,这样做只...

  • 简单使我们快乐

    快乐陪伴环绕在我们身边那是童年时代 我们绝大多数人真实的甜蜜记忆,忧愁与烦 恼一波又一波地来袭没完没了地纠...

  • 冥想使我简单

    冥想,是很好的入定的方法。剥离杂念和痴心妄想,回归本真。甚至,放空一切,让自己安静、简单、纯粹。 冥想,其实也没什...

  • 如何使“难”变得“简单”

    因为熟练,所以简单。难,是因为不熟练。其实,难的部分可以通过不断的锤炼,变成熟,从而简单。这个过程,往往很难坚持下...

  • 信仰使选择变得简单

    刚开始做这件事的时候,我并没有觉得很复杂。怀着对未来的美好憧憬,一步一步的推进着工作。然而理想很丰满,现实却...

  • HttpURLConnection,HttpClient的简单使

    HttpURLConnection 在android 2.2及以下版本中HttpUrlConnection存在着一...

  • 舒畅|简单,使人快乐

    她是《天龙八部》中的天山童姥,从少女到老太太,颠覆性演出;她是《宝莲灯》中的小玉,演绎了一场小狐狸与沉香的爱情故事...

  • iOS开发-UIActivityIndicatorView简单使

    软件开发的时候经常会遇到半天才加载出来数据的情况,不管是程序写的烂,还是说本来网速比较慢,一般都都会给个提示让用户...

  • 如何使生活简单些

    本文摘自quora.com. 人们通常碍于拒绝别人的要求: 忍受与反抗,人们对后者的恐惧更大。 -- 龙纹身的女孩...

网友评论

    本文标题:djangorestframework-simplejwt简单使

    本文链接:https://www.haomeiwen.com/subject/cponyhtx.html