首页 > 其他分享 >【Django进阶】djangorestframework-jwt使用

【Django进阶】djangorestframework-jwt使用

时间:2024-03-13 19:56:38浏览次数:32  
标签:进阶 用户 jwt JWT token 认证 djangorestframework user

【Django进阶】djangorestframework-jwt使用 

 

简介

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

简单一句话理解就是:由服务器经过加密后生成的一张令牌

token的认证和传统的session认证的区别

1. 传统的session认证

我们知道,http协议本身是一种无状态的协议,而这就意味着如果用户向我们的应用提供了用户名和密码来进行用户认证,那么下一次请求时,用户还要再一次进行用户认证才行,因为根据http协议,我们并不能知道是哪个用户发出的请求,所以为了让我们的应用能识别是哪个用户发出的请求,我们只能在服务器存储一份用户登录的信息,这份登录信息会在响应时传递给浏览器,告诉其保存为cookie,以便下次请求时发送给我们的应用,这样我们的应用就能识别请求来自哪个用户了,这就是传统的基于session认证。

但是这种基于session的认证使应用本身很难得到扩展,随着不同客户端用户的增加,独立的服务器已无法承载更多的用户,而这时候基于session认证应用的问题就会暴露出来.

2. 基于session认证所显露的问题

Session:
每个用户经过我们的应用认证之后,我们的应用都要在服务端做一次记录,以方便用户下次请求的鉴别,通常而言session都是保存在内存中,而随着认证用户的增多,服务端的开销会明显增大。
扩展性:
用户认证之后,服务端做认证记录,如果认证的记录被保存在内存中的话,这意味着用户下次请求还必须要请求在这台服务器上,这样才能拿到授权的资源,这样在分布式的应用上,相应的限制了负载均衡器的能力。这也意味着限制了应用的扩展能力。
CSRF:
因为是基于cookie来进行用户识别的, cookie如果被截获,用户就会很容易受到跨站请求伪造的攻击。

3. 基于token的鉴权机制

基于token的鉴权机制类似于http协议也是无状态的,它不需要在服务端去保留用户的认证信息或者会话信息。这就意味着基于token认证机制的应用不需要去考虑用户在哪一台服务器登录了,这就为应用的扩展提供了便利。

JWT配置

安装

pip install djangorestframework
pip install djangorestframework-jwt
INSTALLED_APPS = (
    ...
    'rest_framework',
    'rest_framework_jwt',
    ...
)

REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': (
        'rest_framework_jwt.authentication.JSONWebTokenAuthentication',
        ...
    ),
}

JWT_AUTH = {
    'JWT_EXPIRATION_DELTA': datetime.timedelta(days=7),
    'JWT_ALLOW_REFRESH': True,
}

扩展配置

JWT_AUTH = {
    'JWT_SECRET_KEY': 'your_secret_key',
    'JWT_ALGORITHM': 'HS256',
    'JWT_VERIFY': True,
    'JWT_VERIFY_EXPIRATION': True,
    'JWT_EXPIRATION_DELTA': datetime.timedelta(seconds=3600),
    'JWT_ALLOW_REFRESH': True,
    'JWT_REFRESH_EXPIRATION_DELTA': datetime.timedelta(days=7),
    'JWT_AUTH_HEADER_PREFIX': 'JWT',
}

重写自定义视图函数

from rest_framework_jwt.serializers import JSONWebTokenSerializer
from django.contrib.auth import authenticate
from django.utils.translation import ugettext as _
from rest_framework import serializers
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 TokenSerializer(JSONWebTokenSerializer):
	# 重写JSONWebTokenSerializer的validate函数
    def validate(self, attrs):
        credentials = {
            self.username_field: attrs.get(self.username_field),
            'password': attrs.get('password')
        }

        if all(credentials.values()):
            user = authenticate(**credentials)

            if user:
                if not user.is_active:
                    msg = _('User account is disabled.')
                    raise serializers.ValidationError(msg)

                ###################################
                # 添加一个认证
                if not user.is_staff:
                    msg = _('User account is disabled.')
                    raise serializers.ValidationError(msg)
                ##################################

                payload = jwt_payload_handler(user)
				
                return {
                    'token': jwt_encode_handler(payload),
                    'user': user
                }
            else:
                msg = _('Unable to log in with provided credentials.')
                raise serializers.ValidationError(msg)
        else:
            msg = _('Must include "{username_field}" and "password".')
            msg = msg.format(username_field=self.username_field)
            raise serializers.ValidationError(msg)



########################################
from rest_framework_jwt.views import JSONWebTokenAPIView

class ObtainJSONWebToken(JSONWebTokenAPIView):
    """
    API View that receives a POST with a user's username and password.

    Returns a JSON Web Token that can be used for authenticated requests.
    """
    serializer_class = TokenSerializer

内置接口

from rest_framework_jwt.views import obtain_jwt_token, refresh_jwt_token, verify_jwt_token

urlpatterns = [
    url(r'^auth/token/$', obtain_jwt_token), #获取令牌
    url(r'^auth/token/refresh/$', refresh_jwt_token),  #刷新令牌
    url(r'^auth/token/verify/$', verify_jwt_token),  #验证令牌
]

成功配置返回结果

自定义成功

def jwt_response_payload_handler(token, user=None, request=None):
    """为返回的结果添加用户相关信息"""
    # print(user, request.headers)
    return {
        "status": 200,
        "message": "登录成功",
        "data": {'token': token,
                 'email': user.email,
                 'user_id': user.id,
                 'username': user.username}

    }

setting中配置
jwt载荷中的有效期设置

JWT_AUTH = {
    'JWT_AUTH_HEADER_PREFIX': 'JWT',
    # token 有效期
    'JWT_EXPIRATION_DELTA': datetime.timedelta(seconds=3),
    'JWT_ALLOW_REFRESH': True,
    # 续期有效期(该设置可在24小时内带未失效的token 进行续期)
    'JWT_REFRESH_EXPIRATION_DELTA': datetime.timedelta(hours=24),
    # 自定义返回格式,需要手工创建
    'JWT_RESPONSE_PAYLOAD_HANDLER': 'apps.users.views.jwt_response_payload_handler',
    # 'JWT_RESPONSE_PAYLOAD_ERROR_HANDLER': 'apps.users.views.jwt_response_payload_error_handler',
}

失败自定义返回

/rest_framework_jwt/settings.py在IMPORT_STRINGS中添加

"JWT_RESPONSE_PAYLOAD_ERROR_HANDLER":
    'rest_framework_jwt.utils.jwt_response_payload_handler',


'JWT_RESPONSE_PAYLOAD_ERROR_HANDLER'

rest_framework_jwt/views.py中修改

def jwt_response_payload_error_handler(serializer, request = None):
    return {
        "msg": "用户名或者密码错误",
        "status": 400,
        "detail": serializer.errors
    }

setting配置

jwt_token配置

JWT_AUTH = {
    'JWT_EXPIRATION_DELTA': datetime.timedelta(seconds=6000),
    # 登陆成功自定义 的返回结构
    'JWT_RESPONSE_PAYLOAD_HANDLER': 'Users.views.jwt_response_payload_handler',
    # 登陆失败时自定义的返回结构
    'JWT_RESPONSE_PAYLOAD_ERROR_HANDLER': 'Users.views.jwt_response_payload_error_handler',
}

   

标签:进阶,用户,jwt,JWT,token,认证,djangorestframework,user
From: https://www.cnblogs.com/xiao-xue-di/p/18071389

相关文章

  • 代码随想录算法训练营第四十五天 | 279.完全平方数,322. 零钱兑换,70. 爬楼梯 (进阶)
    57.爬楼梯(第八期模拟笔试)时间限制:1.000S空间限制:128MB题目描述假设你正在爬楼梯。需要n阶你才能到达楼顶。每次你可以爬至多m(1<=m<n)个台阶。你有多少种不同的方法可以爬到楼顶呢?注意:给定n是一个正整数。输入描述输入共一行,包含两个正整数,分......
  • 数据结构进阶
    区间数颜色LOJ#3751.[SDOI2009]HH的项链给定长度为\(n\)的序列,\(m\)次询问\([l,r]\)内有多少不同的元素。\(n\le5\times10^4\),\(m\le2\times10^5\)。区间数颜色是莫队算法的经典应用,可以用莫队在\(\Theta(m\sqrtn)\)内解决。P1972[SDOI2009]HH的项链(数据加......
  • 代码随想录算法训练营第四十五天| ● 70. 爬楼梯 (进阶) ● 322. 零钱兑换 ● 279.完全
    爬楼梯 (进阶)题目链接:57.爬楼梯(第八期模拟笔试)(kamacoder.com)思路:笑嘻了,直接给默写出来了。#include<bits/stdc++.h>usingnamespacestd;intmain(){intn,m;cin>>n>>m;vector<int>dp(n+1);dp[0]=1;for(inti=1;i<=n;i++){for(in......
  • Prompt进阶3:LangGPT(构建高性能质量Prompt策略和技巧2)--稳定高质量文案生成器
    Prompt进阶3:LangGPT(构建高性能质量Prompt策略和技巧2)--稳定高质量文案生成器1.LangGPT介绍现有Prompt创建方法有如下缺点:缺乏系统性:大多是细碎的规则,技巧,严重依赖个人经验缺乏灵活性:对他人分享的优质prompt进行调整需要直接修改prompt内容缺乏交互友好性:优质promp......
  • JWT LL
     1、工作原理"""1)jwt=base64(头部).base(载荷payload).hash256(base64(头部).base(载荷).密钥)2)base64是可逆的算法、hash256是不可逆的算法3)密钥是固定的字符串,保存在服务器""" 2、drf-jwt官网http://getblimp.github.io/django-rest-framework-jwt/......
  • 嵌入式数据库SQlite3-进阶篇
    嵌入式数据库sqlite3-HQ文章目录嵌入式数据库sqlite3-HQ@[toc]嵌入式数据库sqlite3【进阶篇】数据库准备order子句Where子句与逻辑运算符语法实例groupby子句having子句举例函数SQLiteCOUNT函数SQLiteMAX函数SQLiteMIN函数SQLiteAVG函数SQLiteSUM函......
  • 技术笔记(8)git的部分进阶功能
    技术笔记(8)git的部分进阶功能‍学习笔记:‍与分支有关的git操作branch、checkout、merge查看分支:查看当前分支信息:gitbranch查看远程分支信息:gitbranch-r查看所有分支信息,包括本地和远程:gitbranch-a分支与分支:切换到某分支:gitcheckout从当前节点新建......
  • 东华OJ 进阶题30 盾神与砝码称重
    问题描述:有一天,他在宿舍里无意中发现了一个天平!这个天平很奇怪,有n个完好的砝码,但是没有游码。盾神为他的发现兴奋不已!于是他准备去称一称自己的东西。他准备好了m种物品去称。神奇的是,盾神一早就知道这m种物品的重量,他现在是想看看这个天平能不能称出这些物品出来。但是......
  • ansible-playbook剧本 进阶
    剧本的高级特性剧本高级特性是完全遵循python的循环结构来的编程语言特有的逻辑控制语句变量循环等等你的剧本,可以考虑用高级特性,也可以不用高级特性是为了简化剧本比如,创建10个系统的用户ansiblebakcup-muser-a"name=cc01"ansiblebakcup-muser-a"name=cc......
  • 【Python使用】python高级进阶知识md总结第3篇:静态Web服务器-返回指定页面数据,静态We
    python高级进阶全知识知识笔记总结完整教程(附代码资料)主要内容讲述:操作系统,虚拟机软件,Ubuntu操作系统,Linux内核及发行版,查看目录命令,切换目录命令,绝对路径和相对路径,创建、删除文件及目录命令,复制、移动文件及目录命令,终端命令格式的组成,查看命令帮助。HTTP请求报文,HTTP响应报文......