• django-rest-framework-jwt的使用


    一简介

    JWT 是一个开放标准(RFC 7519),它定义了一种用于简洁,自包含的用于通信双方之间以 JSON 对象的形式安全传递信息的方法。该信息可以被验证和信任,因为它是数字签名的。JWTS可以使用秘密(使用HMAC算法)或公钥/私钥对使用RSA或ECDSA来签名。

    JWT的组成部分:

    header

    Header是由下面这个格式的Json通过Base64编码(编码不是加密,是可以通过反编码的方式获取到这个原来的Json,所以JWT中存放的一般是不敏感的信息)生成的字符串,Header中存放的内容是说明编码对象是一个JWT以及使用“SHA-256”的算法进行加密(加密用于生成Signature)

    playload

    Payload是通过Claim进行Base64转码之后生成的一串字符串,Claim是一个Json,Claim中存放的内容是JWT自身的标准属性,所有的标准属性都是可选的,可以自行添加,比如:JWT的签发者、JWT的接收者、JWT的持续时间等;同时Claim中也可以存放一些自定义的属性,这个自定义的属性就是在用户认证中用于标明用户身份的一个属性,比如用户存放在数据库中的id,为了安全起见,一般不会将用户名及密码这类敏感的信息存放在Claim中。将Claim通过Base64转码之后生成的一串字符串称作Payload

    signatrue

    Signature是由Header和Payload组合而成,将Header和Claim这两个Json分别使用Base64方式进行编码,生成字符串Header和Payload,然后将Header和Payload以Header.Payload的格式组合在一起形成一个字符串,然后使用上面定义好的加密算法和一个密匙(这个密匙存放在服务器上,用于进行验证)对这个字符串进行加密,形成一个新的字符串,这个字符串就是Signature

    签名的目的:最后一步签名的过程,实际上是对头部以及负载内容进行签名,防止内容被窜改。如果有人对头部以及负载的内容解码之后进行修改,再进行编码,最后加上之前的签名组合形成新的JWT的话,那么服务器端会判断出新的头部和负载形成的签名和JWT附带上的签名是不一样的。如果要对新的头部和负载进行签名,在不知道服务器加密时用的密钥的话,得出来的签名也是不一样的。

    rest_framework_jwt

    rest_framework_jwt是一个封装了jwt符合restful规范的接口

    网站地址:http://getblimp.github.io/django-rest-framework-jwt/

    安装:pip install djangorestframework-jwt

    二、配合drf的认证组件的使用方法

    配置文件

    #添加rest-framework
    INSTALLED_APPS = [
        'django.contrib.admin',
        'django.contrib.auth',
        'django.contrib.contenttypes',
        'django.contrib.sessions',
        'django.contrib.messages',
        'django.contrib.staticfiles',
        'app01.apps.App01Config',
        "rest_framework",
    ]
    
    REST_FRAMEWORK = {
        # 配置默认的认证方式 base:账号密码验证
        #session:session_id认证
        'DEFAULT_AUTHENTICATION_CLASSES': (
            # drf的这一阶段主要是做验证,middleware的auth主要是设置session和user到request对象
            # 默认的验证是按照验证列表从上到下的验证
            'rest_framework.authentication.BasicAuthentication',
            'rest_framework.authentication.SessionAuthentication',
            "rest_framework_jwt.authentication.JSONWebTokenAuthentication",
        )}
    
    import datetime
    
    # 超时时间
    JWT_AUTH = {
        'JWT_EXPIRATION_DELTA': datetime.timedelta(days=1),
        # token前缀
        'JWT_AUTH_HEADER_PREFIX': 'JWT',
    }
    
    # 引用Django自带的User表,继承使用时需要设置
    AUTH_USER_MODEL = "app01.User"

    模型表

    #使用django自带的auth组件模型表
    from django.db import models
    from django.contrib.auth.models import AbstractUser
    # Create your models here.
    class User(AbstractUser):
        phone=models.CharField(max_length=11,null=True)

    url路由层

    from django.conf.urls import url
    from django.contrib import admin
    from rest_framework_jwt.views import obtain_jwt_token
    from app01 import views
    urlpatterns = [
        url(r'^admin/', admin.site.urls),
        # url(r'^home/',  views.Home.as_view()),
        # 登入验证,使用JWT的模块,只要用户密码正确会自动生成一个token返回
        url(r'^login/', obtain_jwt_token),
        # 访问需要认证的接口
        url(r'^index/', views.Index.as_view()),
    ]

    view视图层

    from django.shortcuts import render
    from django.http import JsonResponse
    
    # Create your views here.
    from rest_framework.views import APIView
    from app01.jwtMiddleware import TokenAuth
    
    
    class Index(APIView):
      #局部认证的配置 authentication_classes
    = [TokenAuth,] def get(self,request): return JsonResponse({"index":"ok"}) class Home(APIView): def get(self,request): return render(request,"login.html")

    rest-framework认证类

    from rest_framework.exceptions import AuthenticationFailed
    from rest_framework_jwt.serializers import VerifyJSONWebTokenSerializer
    
    
    class TokenAuth():
        def authenticate(self, request):
            token={"token":None}
            # print(request.META.get("HTTP_TOKEN"))
            token["token"] = request.META.get('HTTP_TOKEN')
            valid_data = VerifyJSONWebTokenSerializer().validate(token)
            print(valid_data)
            user = valid_data['user']
            print(user)
            if user:
                return
            else:
                raise AuthenticationFailed('认证失败')

    模板

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
    <form action="/login/" method="post">
        <input type="text" name="username">
        <input type="text" name="password">
        <input type="submit" value="登录">
    </form>
    </body>
    </html>

    postman

     

  • 相关阅读:
    C++设计模式-Adapter适配器模式
    创业进行时之用户注册
    毕业三年
    献给在这个世界上摇摆不定的朋友们
    调用一个系统命令,并读取它的输出值(使用QProcess.readAll)
    Delphi自写组件:可设置颜色的按钮(改成BS_OWNERDRAW风格,然后CN_DRAWITEM)
    Delphi透明组件开发(去掉自己的csOpaque,去掉父控件的WS_CLIPCHILDREN,增加WS_EX_TRANSPARENT,截获WM_ERASEBKGND,然后在WM_DRAWITEM里画) good
    读一读Scktsrvr.exe的源程序
    窗口显示于parent控件上(用到了ManualDock函数)
    终于说再见了!Google Reader
  • 原文地址:https://www.cnblogs.com/angelyan/p/10902551.html
Copyright © 2020-2023  润新知