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

【Django进阶】djangorestframework-jwt使用

时间:2023-12-28 14:56:53浏览次数:27  
标签:进阶 用户 jwt JWT token 认证 djangorestframework user

简介

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/fuchangjiang/p/17932711.html

相关文章

  • HTML学习第七天:JavaScript进阶与事件处理
    在今天的HTML学习中,我进一步深入了JavaScript的学习,特别是事件处理方面。早上,我回顾了昨天学习的JavaScript基础知识,并进行了一些练习,以加深自己的理解。然后,我开始学习事件处理。事件处理是JavaScript中非常重要的一部分,它允许我们响应用户的各种操作,如点击、滑动、键盘输入等。我......
  • c#语法JWT请求接口
    NuGet下载System.IdentityModel.Tokens.Jwt包下面是获取token,需要引用对应的jwtusingSystem.IdentityModel.Tokens.Jwt;usingMicrosoft.IdentityModel.Tokens;privatevoidbutton1_Click(objectsender,EventArgse){stringsecretId="a1bc3900b......
  • Redis进阶 使用Lua编写Redis脚本
    前面学习了Lua的基本语法,接下来是使用Lua编写脚本1.可以使用redis.call来调用redis命令使用redis.call会将redis命令返回的类型转换成对应的Lua数据类型。关系如下 与redis.call想类似的就是redis.pcall。【redis.call与redis.pcall的区别】当命令出错的时候,redis.pcall......
  • Python进阶
    Object介绍  Python的Object是一种数据抽象或者数据结构抽象,Object应该同时具备:本征值(Indentity)、型式(Type)、值(Value)三个参数。a=45print(id(a))#表示在python中的唯一内存地址,具备唯一性print(type(a))print(a)/*-----output-------*/2063144480432<class'int'>......
  • 【Cpp 语言基础】 string 类型进阶使用
    大纲:1.特殊的初始化方式2.获取子串3.与<algorith>中对应的成员函数 ”串“类型类似于数组类型(C语言的字符串就是字符数组)。但是有一点不同之处,就是串经常作为一个整体才有实际的”意义“,而数组每个单元都有其”意义“。因此,“串”的操作中,很大部分是“串”的整体、局部......
  • JWT 简介与 C# 示例
    〇、什么是JWT?JWT,即JSONWebToken,是一种基于JSON的开放标准(RFC7519),主要用于在网络应用环境间安全地传递声明。这种声明被进行了数字签名,可以验证和信任,因此,它适用于各种需要信息安全性和无状态的应用。在具体加密过程中,客户端会使用RSA算法生成JWT串,这里用到了私钥“......
  • Linux进阶(二)
    一、常用的一些基本命令1、管理文件和目录的命令命令功能命令功能pwd显示当前目录ls查看目录下的内容cd改变所在目录cat显示文件的内容grep在文件中查找某字符cp复制文件touch创建文件mv移动文件rm删除文件rmdir删除目录2、在文件系统中查找文件和目录find/home/soft-name"file_......
  • 《Kubernetes从入门到进阶》之一: 认识Kubernetes
    01容器技术在早期的传统架构中,应用程序是直接部署在物理机上的。在这种场景下,由于无法对程序的资源使用进行限制,容易出现不同程序争抢资源的问题,并且程序之间还可能互相影响。这使得往往需要按照应用来划分机器,并造成了较大的资源浪费。 后来,虚拟机(VM)的出现改变了这种现状。......
  • Redis进阶 Lua函数
    1.可以直接声明一个局部变量来接收函数,也可以直接简写localsquare=function(i)returni*iend简写:localfunctionsquare(i)returni*iend 2.当调用函数时,参数是一一对应的,如果多了参数,则会忽略,少则会将对应位置的参数赋值为nil 3.如果想要实现可变参数个数,也......
  • Java技术得这样进阶,天天CRUD就完蛋了
    Java天天CRUD,技术没提高怎么办?技术进阶得这么搞,才能进阶为高级开发和架构师?资料地址:自学精灵-IT技术星球(也可以百度搜:自学精灵)。首先点明,只写业务代码是无法成长技术的。提升技术的两个方法是:有技术大佬带有技术大佬的资料本文介绍靠谱的技术进阶资料,让你比其他人更有竞争力!本文......