Django REST Framework完整教程-认证与权限-JWT的使用

文章目录

    • 1.认证(Authentication)与权限(Permission)
      • 1.1.视图添加权限
      • 1.2.登录验证
      • 1.3.常用DRF自带权限类
      • 1.4.自定义权限类
      • 1.5.全局权限
      • 1.6.函数视图权限
    • 2.认证详解
      • 2.1.认证方案
      • 2.2.如何使用TokenAuthentication?
    • 3.JSON Web Token(JWT)认证
      • 3.1.工作原理
      • 3.2.安装
      • 3.3.使用
      • 3.4.更改Simple JWT的默认设置
      • 3.5.自定义令牌(token)
      • 3.6.自定义认证后台(Backend)

阅读本文之前,请读者先阅读: https://plugin.blog.csdn.net/article/details/133853377,如果已经知晓Django REST Framework的基础,可以继续阅读本文内容。

1.认证(Authentication)与权限(Permission)

认证(Authentication)与权限(Permission)不是一回事。认证是通过用户提供的用户ID/密码组合或者Token来验证用户的身份。权限(Permission)的校验发生验证用户身份以后,是由系统根据分配权限确定用户可以访问何种资源以及对这种资源进行何种操作,这个过程也被称为授权(Authorization)。
无论是Django还是DRF, 当用户成功通过身份验证以后,系统会把已通过验证的用户对象与request请求绑定,这样一来你就可以使用request.user获取这个用户对象的所有信息了。

在前面的教程中我们编写ArticleList和ArticleView两个基于类的视图(如下所示)。前者如果收到GET请求会返回文章资源列表,如果收到POST请求则添加文章;后者如果收到GET请求就返回单篇文章资源,如果收到PUT或DELETE请求,就对文章资源进行修改或删除。

# coding=utf-8
from .models import Article
from .serializers import ArticleSerializer# generic class-based views
from rest_framework import genericsclass ArticleList(generics.ListCreateAPIView):queryset = Article.objects.all()serializer_class = ArticleSerializer# 将request.user与author绑定def perform_create(self, serializer):serializer.save(author=self.request.user)class ArticleDetail(generics.RetrieveUpdateDestroyAPIView):queryset = Article.objects.all()serializer_class =ArticleSerializer

以上两个视图其实是有很大问题的,因为任何用户包括匿名用户也可以对文章资源进行修改。比如当你访问单篇文章资源时,你不仅可以看到红色的delete按钮和修改文章内容的表单,而且可以在未登录的情况对它们进行操作。

1.1.视图添加权限

在Django传统视图开发中你可能会使用@login_required和@permission_required这样的装饰器要求用户先登录或进行权限验证。在DRF中你不需要做,这是因为REST framework 包含许多默认权限类,我们可以用来限制谁可以访问给定的视图。在这种情况下,我们需要的是 IsAuthenticatedOrReadOnly 类,它将确保经过身份验证的请求获得读写访问权限,未经身份验证的请求将获得只读读的权限。
现在修改我们的视图(zlblog/views.py),添加如下代码:

from rest_framework import generics
from rest_framework import permissions
from .permissions import IsOwnerOrReadOnlyclass ArticleList(generics.ListCreateAPIView):queryset = Article.objects.all()serializer_class = ArticleSerializerpermission_classes = (permissions.IsAuthenticatedOrReadOnly,)# importantdef perform_create(self, serializer):serializer.save(author=self.request.user)class ArticleDetail(generics.RetrieveUpdateDestroyAPIView):queryset = Article.objects.all()serializer_class =ArticleSerializerpermission_classes = (permissions.IsAuthenticatedOrReadOnly,)

此时再访问文章资源列表或单篇文章资源时,你会看到红色的delete按钮和添加修改表单都已消失。当你重新登录验证身份后,你又可以看到delete按钮和修改表单了。

1.2.登录验证

你可能会问,DRF中用户应该访问哪个url登录验证身份呢? 是admin吗?当然不是admin页面,因为只有管理员才能通过admin页面登录。DRF中你可以将登录页面api-auth添加到你的项目urls中,如下所示:

#apiproject/urls.py
from django.contrib import admin
from django.urls import path, includeurlpatterns = [path('admin/', admin.site.urls),path('v1/', include('zlblog.urls')),#包含zlblog中的urlspath('api-auth/', include('rest_framework.urls')), # 用户登录页面
]

然后访问http://127.0.0.1:8000/api-auth/login/你就可以看到专门的DRF的登录页面了,如下所示:
在这里插入图片描述

1.3.常用DRF自带权限类

除了IsAuthenticatedOrReadOnly 类,DRF自带的常用权限类还包括:

IsAuthenticated类:仅限已经通过身份验证的用户访问;
AllowAny类:允许任何用户访问;
IsAdminUser类:仅限管理员访问;
DjangoModelPermissions类:只有在用户经过身份验证并分配了相关模型权限时,才会获得授权访问相关模型。
DjangoModelPermissionsOrReadOnly类:与前者类似,但可以给匿名用户访问API的可读权限。
DjangoObjectPermissions类:只有在用户经过身份验证并分配了相关对象权限时,才会获得授权访问相关对象。通常与django-gaurdian联用实现对象级别的权限控制。

1.4.自定义权限类

IsAuthenticatedOrReadOnly 类并不能实现只有文章 article 的创建者才可以更新或删除它,这时我们还需要自定义一个名为IsOwnerOrReadOnly 的权限类,把它加入到ArticleDetail视图里。
首先我们在zlblog文件夹下创建permissions.py,添加如下代码:

# coding=utf-8
from rest_framework import permissionsclass IsOwnerOrReadOnly(permissions.BasePermission):"""自定义权限只允许对象的创建者才能编辑它。"""def has_object_permission(self, request, view, obj):# 读取权限被允许用于任何请求,# 所以我们始终允许 GET,HEAD 或 OPTIONS 请求。if request.method in permissions.SAFE_METHODS:return True# 写入权限只允许给 article 的作者。return obj.author == request.user

然后修改我们的视图,IsOwnerOrReadOnly 的权限类,把它加入到ArticleDetail视图的permission_classes里。这样就完美实现了文初我们想要实现的三个功能。DRF支持权限类的插拔,是不是很帅?

1.5.全局权限

在前面的案例中,我们都是在基于类的API视图里通过permission_classes属性设置的权限类。如果你有些权限是全局或全站通用的,你还可以在settings.py中使用 DEFAULT_PERMISSION_CLASSES 全局设置默认权限策略。

REST_FRAMEWORK = {'DEFAULT_PERMISSION_CLASSES': ('rest_framework.permissions.IsAuthenticated',)
}

如果未指定,则此设置默认为允许无限制访问:

'DEFAULT_PERMISSION_CLASSES': ('rest_framework.permissions.AllowAny',
)

1.6.函数视图权限

如果你习惯使用基于函数的视图编写API,你可以按如下方式给你的函数视图添加权限。

from rest_framework.decorators import api_view, permission_classes
from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response@api_view(['GET'])
@permission_classes((IsAuthenticated, ))
def example_view(request, format=None):content = {'status': 'request was permitted'}return Response(content)

注意:当通过类属性或装饰器设置新的权限类时,您会告诉视图忽略 settings.py 文件上设置的默认列表。

2.认证详解

身份验证是将传入的请求对象(request)与一组标识凭据(例如请求来自的用户或其签名的令牌token)相关联的机制。REST framework 提供了一些开箱即用的身份验证方案,并且还允许你实现自定义方案。

DRF的每个认证方案实际上是一个类。你可以在视图中使用一个或多个认证方案类。REST framework 将尝试使用列表中的每个类进行身份验证,并使用成功完成验证的第一个类的返回的元组设置 request.user 和request.auth。

用户通过认证后request.user返回Django的User实例,否则返回AnonymousUser的实例。request.auth通常为None。如果使用token认证,request.auth可以包含认证过的token。

2.1.认证方案

Session认证SessionAuthentication类:此认证方案使用Django的默认session后端进行身份验证。当客户端发送登录请求通过验证后,Django通过session将用户信息存储在服务器中保持用户的请求状态。Session身份验证适用于与你的网站在相同的Session环境中运行的AJAX客户端 (注:这也是Session认证的最大弊端)。

基本认证BasicAuthentication类:此认证方案使用HTTP 基本认证,针对用户的用户名和密码进行认证。使用这种方式后浏览器会跳出登录框让用户输入用户名和密码认证。基本认证通常只适用于测试。

远程认证RemoteUserAuthentication类:此认证方案为用户名不存在的用户自动创建用户实例。这个很少用,具体见文档。

Token认证TokenAuthentication类:该认证方案是DRF提供的使用简单的基于Token的HTTP认证方案。当客户端发送登录请求时,服务器便会生成一个Token并将此Token返回给客户端,作为客户端进行请求的一个标识以后客户端只需带上这个Token前来请求数据即可,无需再次带上用户名和密码。后面我们会详细介绍如何使用这种认证方案。

注意:如果你在生产环境下使用BasicAuthentication和TokenAuthentication认证,你必须确保你的API仅在https可用。

如何在DRF中使用你的认证方案 ?
方式1:settings.py中设置默认的全局认证方案

REST_FRAMEWORK = {'DEFAULT_AUTHENTICATION_CLASSES': ('rest_framework.authentication.BasicAuthentication','rest_framework.authentication.SessionAuthentication',)}

**方式2:基于类的视图(CBV)中使用-authentication_classes **

from rest_framework.authentication import SessionAuthentication, BasicAuthentication
from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response
from rest_framework.views import APIViewclass ExampleView(APIView):authentication_classes = (SessionAuthentication, BasicAuthentication)permission_classes = (IsAuthenticated,)

方式3:函数视图中使用

@api_view(['GET'])
@authentication_classes((SessionAuthentication, BasicAuthentication))
@permission_classes((IsAuthenticated,))
def example_view(request, format=None):content = {'user': unicode(request.user),  # `django.contrib.auth.User` 实例。'auth': unicode(request.auth),  # None}return Response(content)

如何自定义认证方案?
要实现自定义的认证方案,要继承BaseAuthentication类并且重写.authenticate(self, request)方法。如果认证成功,该方法应返回(user, auth)的二元元组,否则返回None。
以下示例将以自定义请求标头中名称为’X_USERNAME’提供的用户名作为用户对任何传入请求进行身份验证,其它类似自定义认证需求比如支持用户同时按用户名或email进行验证。

from django.contrib.auth.models import User
from rest_framework import authentication
from rest_framework import exceptionsclass ExampleAuthentication(authentication.BaseAuthentication):def authenticate(self, request):username = request.META.get('X_USERNAME')if not username:return Nonetry:user = User.objects.get(username=username)except User.DoesNotExist:raise exceptions.AuthenticationFailed('No such user')return (user, None)

2.2.如何使用TokenAuthentication?

DRF自带的TokenAuthentication方案可以实现基本的token认证,整个流程如下:
首先,你需要将修改settings.py, 加入如下app。

INSTALLED_APPS = (...'rest_framework.authtoken')

后文再单独讲解一个例子。

3.JSON Web Token(JWT)认证

然而JSON Web Token(JWT)是一种更新的使用token进行身份认证的标准。与DRF内置的TokenAuthentication方案不同,JWT身份验证不需要使用数据库来验证令牌, 而且可以轻松设置token失效期或刷新token, 是API开发中当前最流行的跨域认证解决方案。本文将详细介绍JWT认证的工作原理以及如何通过djangorestframework-simplejwt 这个第三方包轻松实现JWT认证。

3.1.工作原理

JSON Web Token(JWT)是一种开放标准,它定义了一种紧凑且自包含的方式,用于各方之间安全地将信息以JSON对象传输。由于此信息是经过数字签名的,因此可以被验证和信任。JWT用于为应用程序创建访问token,通常适用于API身份验证和服务器到服务器的授权。那么如何理解紧凑和自包含这两个词的含义呢?

  • 紧凑:就是说这个数据量比较少,可以通过url参数,http请求提交的数据以及http header多种方式来传递。
  • 自包含:这个字符串可以包含很多信息,比如用户id,用户名,订单号id等,如果其他人拿到该信息,就可以拿到关键业务信息。

那么JWT认证是如何工作的呢? 首先客户端提交用户登录信息验证身份通过后,服务器生成一个用于证明用户身份的令牌(token),也就是一个加密后的长字符串,并将其发送给客户端。在后续请求中,客户端以各种方式(比如通过url参数或者请求头)将这个令牌发送回服务器,服务器就知道请求来自哪个特定身份的用户了。
在这里插入图片描述
JSON Web Token由三部分组成,这些部分由点(.)分隔,分别是header(头部),payload(有效负载)和signature(签名)。

header(头部): 识别以何种算法来生成签名;
pyload(有效负载): 用来存放实际需要传递的数据;
signature(签名): 安全验证token有效性,防止数据被篡改。

通过http传输的数据实际上是加密后的JWT,它是由两个点分割的base64-URL长字符串组成,解密后我们可以得到header, payload和signature三部分。我们可以简单的使用 https://jwt.io/ 官网来生成或解析一个JWT,如下所示:
在这里插入图片描述

接下来我们将使用django-rest-framework-simplejwt这个第三方软件包进行JWT身份验证。
django-rest-framework-simplejwt为Django REST框架提供了JSON Web令牌认证后端。它提供一组保守的默认功能来涵盖了JWT的最常见用例。它还非常容易扩展。

3.2.安装

pip install djangorestframework-simplejwt

3.3.使用

首先,我们需要告诉DRF我们使用jwt认证作为后台认证方案。修改apiproject/settings.py:

REST_FRAMEWORK = {'DEFAULT_FILTER_BACKENDS': ['django_filters.rest_framework.DjangoFilterBackend'],'DEFAULT_AUTHENTICATION_CLASSES': ['rest_framework_simplejwt.authentication.JWTAuthentication',],
}

其次,我们需要提供用户可以获取和刷新token的urls地址,这两个urls分别对应TokenObtainPairView和TokenRefreshView两个视图。

# coding=utf-8
# apiproject/urls.py
from django.contrib import admin
from django.urls import path, include
from rest_framework.routers import DefaultRouter
from django.conf import settings
from django.conf.urls.static import static
from rest_framework_simplejwt.views import (TokenObtainPairView,TokenRefreshView,
)urlpatterns = [path('admin/', admin.site.urls),path('token/', TokenObtainPairView.as_view(), name='token_obtain_pair'),path('token/refresh/', TokenRefreshView.as_view(), name='token_refresh'),path('v1/', include('zlblog.urls')), #包含其它页面的路由地址
]if settings.DEBUG:urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

最后,我们可以开始使用postman测试了。通过POST方法发送登录请求到http://127.0.0.1:8000/token/, 请求数据包括username和password。如果登录成功,你将得到两个长字符串,一个是access token(访问令牌),还有一个是refresh token(刷新令牌),如下所示:
在这里插入图片描述
但是,这里引发了跨域问题。安装跨越库文件:

pip install django-cors-headers

修改setting.py文件,有两处,如下所示:

INSTALLED_APPS = ['django.contrib.admin','django.contrib.auth','django.contrib.contenttypes','django.contrib.sessions','django.contrib.messages','django.contrib.staticfiles','rest_framework','corsheaders',  # 注册跨域app'zlblog','rest_framework.authtoken'
]MIDDLEWARE = ['django.middleware.security.SecurityMiddleware','django.contrib.sessions.middleware.SessionMiddleware','corsheaders.middleware.CorsMiddleware',  # 跨域中间件'django.middleware.locale.LocaleMiddleware',        #支持中文语言'django.middleware.common.CommonMiddleware','django.middleware.csrf.CsrfViewMiddleware','django.contrib.auth.middleware.AuthenticationMiddleware','django.contrib.messages.middleware.MessageMiddleware','django.middleware.clickjacking.XFrameOptionsMiddleware',
]

然后再用postman仿真就可以得到结果:
在这里插入图片描述
修改上文有一个受保护的视图(比如这里的/articles/),权限(permission_classes)是IsAuthenticated,只有验证用户才可访问。如果未授权,返回如下结果:
在这里插入图片描述
访问这个保护视图时你只需要在请求头的Authorization选项里输入你刚才获取的access token即可,如下所示:
在这里插入图片描述
DRF接口会自定验证token的有效性。
不给这个access token默认只有5分钟有效。5分钟过后,当你再次访问保护视图时,你将得到如下token已失效或过期的提示。
那么问题来了,Simple JWT中的access token默认有效期是5分钟,那么refresh token默认有效期是多长呢? 答案是24小时

3.4.更改Simple JWT的默认设置

Simple JWT的默认设置如下所示:

# JWT配置
SIMPLE_JWT = {'ACCESS_TOKEN_LIFETIME': timedelta(minutes=5),  # Access Token的有效期'REFRESH_TOKEN_LIFETIME': timedelta(days=7),  # Refresh Token的有效期# 对于大部分情况,设置以上两项就可以了,以下为默认配置项目,可根据需要进行调整# 是否自动刷新Refresh Token'ROTATE_REFRESH_TOKENS': False,  # 刷新Refresh Token时是否将旧Token加入黑名单,如果设置为False,则旧的刷新令牌仍然可以用于获取新的访问令牌。需要将'rest_framework_simplejwt.token_blacklist'加入到'INSTALLED_APPS'的配置中'BLACKLIST_AFTER_ROTATION': False,  'ALGORITHM': 'HS256',  # 加密算法'SIGNING_KEY': settings.SECRET_KEY,  # 签名密匙,这里使用Django的SECRET_KEY# 如为True,则在每次使用访问令牌进行身份验证时,更新用户最后登录时间"UPDATE_LAST_LOGIN": False, # 用于验证JWT签名的密钥返回的内容。可以是字符串形式的密钥,也可以是一个字典。"VERIFYING_KEY": "","AUDIENCE": None,# JWT中的"Audience"声明,用于指定该JWT的预期接收者。"ISSUER": None, # JWT中的"Issuer"声明,用于指定该JWT的发行者。"JSON_ENCODER": None, # 用于序列化JWT负载的JSON编码器。默认为Django的JSON编码器。"JWK_URL": None, # 包含公钥的URL,用于验证JWT签名。"LEEWAY": 0, # 允许的时钟偏差量,以秒为单位。用于在验证JWT的过期时间和生效时间时考虑时钟偏差。# 用于指定JWT在HTTP请求头中使用的身份验证方案。默认为"Bearer""AUTH_HEADER_TYPES": ("Bearer",), # 包含JWT的HTTP请求头的名称。默认为"HTTP_AUTHORIZATION""AUTH_HEADER_NAME": "HTTP_AUTHORIZATION", # 用户模型中用作用户ID的字段。默认为"id"。"USER_ID_FIELD": "id",# JWT负载中包含用户ID的声明。默认为"user_id"。"USER_ID_CLAIM": "user_id",# 用于指定用户身份验证规则的函数或方法。默认使用Django的默认身份验证方法进行身份验证。"USER_AUTHENTICATION_RULE": "rest_framework_simplejwt.authentication.default_user_authentication_rule",#  用于指定可以使用的令牌类。默认为"rest_framework_simplejwt.tokens.AccessToken"。"AUTH_TOKEN_CLASSES": ("rest_framework_simplejwt.tokens.AccessToken",),# JWT负载中包含令牌类型的声明。默认为"token_type"。"TOKEN_TYPE_CLAIM": "token_type",# 用于指定可以使用的用户模型类。默认为"rest_framework_simplejwt.models.TokenUser"。"TOKEN_USER_CLASS": "rest_framework_simplejwt.models.TokenUser",# JWT负载中包含JWT ID的声明。默认为"jti"。"JTI_CLAIM": "jti",# 在使用滑动令牌时,JWT负载中包含刷新令牌过期时间的声明。默认为"refresh_exp"。"SLIDING_TOKEN_REFRESH_EXP_CLAIM": "refresh_exp",# 滑动令牌的生命周期。默认为5分钟。"SLIDING_TOKEN_LIFETIME": timedelta(minutes=5),# 滑动令牌可以用于刷新的时间段。默认为1天。"SLIDING_TOKEN_REFRESH_LIFETIME": timedelta(days=1),# 用于生成访问令牌和刷新令牌的序列化器。"TOKEN_OBTAIN_SERIALIZER": "rest_framework_simplejwt.serializers.TokenObtainPairSerializer",# 用于刷新访问令牌的序列化器。默认"TOKEN_REFRESH_SERIALIZER": "rest_framework_simplejwt.serializers.TokenRefreshSerializer",# 用于验证令牌的序列化器。"TOKEN_VERIFY_SERIALIZER": "rest_framework_simplejwt.serializers.TokenVerifySerializer",# 用于列出或撤销已失效JWT的序列化器。"TOKEN_BLACKLIST_SERIALIZER": "rest_framework_simplejwt.serializers.TokenBlacklistSerializer",# 用于生成滑动令牌的序列化器。"SLIDING_TOKEN_OBTAIN_SERIALIZER": "rest_framework_simplejwt.serializers.TokenObtainSlidingSerializer",# 用于刷新滑动令牌的序列化器。"SLIDING_TOKEN_REFRESH_SERIALIZER": "rest_framework_simplejwt.serializers.TokenRefreshSlidingSerializer",
}

如果要覆盖Simple JWT的默认设置,可以修改settings.py, 如下所示。下例将refresh token的有效期改为了15天。

from datetime import timedeltaSIMPLE_JWT = {'REFRESH_TOKEN_LIFETIME': timedelta(days=15),'ROTATE_REFRESH_TOKENS': True,
}

3.5.自定义令牌(token)

如果你对Simple JWT返回的access token进行解码,你会发现这个token的payload数据部分包括token类型,token失效时间,jti(一个类似随机字符串)和user_id。如果你希望在payload部分提供更多信息,比如用户的username,这时你就要自定义令牌(token)了。
首先,编写你的zlblog/seralizers.py,添加如下代码。该序列化器继承了TokenObtainPairSerializer类。

from rest_framework_simplejwt.serializers import TokenObtainPairSerializerclass MyTokenObtainPairSerializer(TokenObtainPairSerializer):@classmethoddef get_token(cls, user):token = super(MyTokenObtainPairSerializer, cls).get_token(user)# Add custom claimstoken['username'] = user.usernamereturn token

其次,不使用Simple JWT提供的默认视图,使用自定义视图。修改zlblog/views.py, 添加如下代码:

from rest_framework_simplejwt.views import TokenObtainPairView
from rest_framework.permissions import AllowAny
from .serializers import MyTokenObtainPairSerializerclass MyObtainTokenPairView(TokenObtainPairView):permission_classes = (AllowAny,)serializer_class = MyTokenObtainPairSerializer

最后,修改zlblog/urls.py, 添加如下代码,将/token/指向新的自定义的视图。注意:本例中的app名为zlblog,所以是从zlblog.views导入的MyObtainTokenPairView。

# coding=utf-8
from django.contrib import admin
from django.urls import path, include
from zlblog.views import MyObtainTokenPairView
from rest_framework.routers import DefaultRouter
from django.conf import settings
from django.conf.urls.static import static
from rest_framework_simplejwt.views import TokenRefreshViewurlpatterns = [path('admin/', admin.site.urls),path('token/', MyObtainTokenPairView.as_view(), name='token_obtain_pair'),#自定义tokenpath('token/refresh/', TokenRefreshView.as_view(), name='token_refresh'),path('v1/', include('zlblog.urls')), #包含其它页面的路由地址
]if settings.DEBUG:urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

重新发送POST请求到/token/,你将获得新的access token和refresh token。采用 https://jwt.io/ 解码,在负载部分将得到新的字段名:
在这里插入图片描述
对重新获取的access token进行解码,你将看到payload部分多了username的内容,是不是很酷? 在实际API开发过程中,通过Json Web Token传递更多数据非常有用。

3.6.自定义认证后台(Backend)

上面的演示案例是通过用户名和密码登录的,如果我们希望后台同时支持邮箱/密码,手机/密码组合登录怎么办? 这时我们还需要自定义认证后台(Backend)。
首先,修改zlblog/views.py, 添加如下代码:

# coding=utf-8
from django.contrib.auth.backends import ModelBackend
#django的Q对象将SQL表达式封装在Python对象中,该对象可用于与数据库相关的操作。使用Q对象,我们可以使用更少和更简单的代码进行复杂查询。
from django.db.models import Q
from django.contrib.auth import get_user_modelUser = get_user_model()class MyCustomBackend(ModelBackend):def authenticate(self, request, username=None, password=None, **kwargs):try:user = User.objects.get(Q(username=username) | Q(email=username) )if user.check_password(password):return userexcept Exception as e:return None

其次,修改zlblog/settings.py, 把你自定义的验证方式添加到AUTHENTICATION_BACKENDS里去。

AUTHENTICATION_BACKENDS = ('zlblog.views.MyCustomBackend',
)

修改好后,你使用postman发送邮箱/密码组合到/token/,将同样可以获得access token和refresh token。是不是又学到了一招?

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/162727.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Java学习笔记(四)——程序控制结构

一、顺序控制 二、分支控制 (一)单分支 (二)双分支 (三)多分支 (四)嵌套分支 (五)switch分支结构 (六)if和switch的选择 三、循…

Megatron-LM GPT 源码分析(一) Tensor Parallel分析

引用 本文基于开源代码 https://github.com/NVIDIA/Megatron-LM ,通过GPT的模型运行示例,从三个维度 - 模型结构、代码运行、代码逻辑说明 对其源码做深入的分析。 Tensor Parallel源码分析

uniapp(uncloud) 使用生态开发接口详情4(wangeditor 富文本, 云对象, postman 网络请求)

wangeditor 官网: https://www.wangeditor.com/v4/pages/01-%E5%BC%80%E5%A7%8B%E4%BD%BF%E7%94%A8/01-%E5%9F%BA%E6%9C%AC%E4%BD%BF%E7%94%A8.html 这里用vue2版本,用wangeditor 4 终端命令: npm i wangeditor --save 开始使用 在项目pages > sy_news > add.vue 页面中…

免密码方式获取Hive元数据

前言 开发中可能用到hive的元数据信息 ,如获取hive表列表、hive表字段、hive表数据量大小、hive表文件大小等信息,要想获取hive元数据信息即需要hive元数据库的账号及密码,此次提供的是一种不需要hive元数据库密码及可获取元数据信息的方式,且此种方式是只读 组件:hive …

程序员必备的IP查询工具

shigen坚持日更的博客写手,擅长Java、python、vue、shell等编程语言和各种应用程序、脚本的开发。坚持记录和分享从业两年以来的技术积累和思考,不断沉淀和成长。 hello,今天shigen给大家分享一下如何优雅的查询IP的工具。我们先看一下效果&a…

CSS的美化(文字、背景) Day02

一、文字控制属性 分为:字体样式属性 、文本样式属性 1.1 CSS字体样式属性 1.color定义元素内文字颜色2.font-size 字号大小3 font-family 字体4 font-weight 字体粗细5.font-style 字体风格6.font 字体综合属性 1.1.1 > 文字颜色 color 属性名: color color …

序列化和反序列化指令在PLC通信上的应用

在了解本篇博客之前,大家可以熟悉下序列化指令的相关介绍,详细内容如下: 博途PLC 1200/1500 PLC 序列化和反序列化指令编程应用_博图序列化和反序列化-CSDN博客序列化最重要的作用:在传递和保存对象时.保证对象的完整性和可传递性。对象转换为有序字节流,以便在网络上传输…

在 Python 脚本中设置环境变量

环境变量是与系统进程交互的一种深入方式; 它允许用户获得有关系统属性、路径和已经存在的变量的更详细信息。 我们如何使用环境变量 如上所述,环境变量促使我们与系统进程进行交互。 我们可以使用环境变量来访问系统中的所有变量和键。 为此&#xff…

6 个可解锁部分 GPT-4 功能的 Chrome 扩展(无需支付 ChatGPT Plus 费用)

在过去的几个月里,我广泛探索了 ChatGPT 的所有可用插件。在此期间,我发现了一些令人惊叹的插件,它们改进了我使用 ChatGPT 的方式,但现在,我将透露一些您需要了解的内容。 借助 Chrome 扩展程序,所有 Chat…

Windows:VS Code IDE安装ESP-IDF【保姆级】

物联网开发学习笔记——目录索引 Visual Studio Code(简称“VS Code”)是Microsoft向开发者们提供的一款真正的跨平台编辑器。 参考: VS Code官网:Visual Studio Code - Code Editing. Redefined 乐鑫官网:ESP-IDF…

分类算法-逻辑回归与二分类

1、逻辑回归的应用场景 广告点击率是否为垃圾邮件是否患病金融诈骗虚假账号 看到上面的例子,我们可以发现其中的特点,那就是都属于两个类别之间的判断。逻辑回归就是解决二分类问题的利器。 2、 逻辑回归的原理 2.1 输入 逻辑回归的输入就是一个线性…

python二次开发CATIA:CATIA Automation

CATIA 软件中有一套逻辑与关系都十分严谨的自动化对象,它们从CATIA(Application)向下分支。每个自动化对象(Automation Object,以下简称Object)都有各自的属性与方法。我们通过程序语言调用这些 Object 的属性与方法,便…

C语言 内存

内存分配 内存分配的类型 C/C中内存分为5个区,分别为栈区、堆区、全局/静态存储区、常量存储区、代码区 静态内存分配:编译时分配,包括全局、静态全局、静态局部三种变量。 动态内存分配:运行时分配,包括栈&#x…

SVM支持向量机

定义 支持向量机(SVM),Supported Vector Machine,基于线性划分,输出一个最优化的分隔超平面,该超平面不但能将两类正确分开,且使分类间隔(margin)最大 **所有训练数据点距离最优分类超平面的距离都要大于支持向量距离…

【docker】查看容器日志

目录 一.通过查找宿主机日志路径,通过Linux命令查看即可。 1.1 查看容器日志路径 1.2 按照日志路径检索日志 二、通过docker命令检索日志 2.1 查看指定时间后的日志,只显示最后20行 2.2 查看最近10分钟的日志 2.3 查看某时间段之后的日志 2.4 查…

SpringCloud-Nacos

一、介绍 (1)作为服务注册中心和配置中心 (2)等价于:EurekaConfigBus (3)nacos集成了ribbon,支持负载均衡 二、安装 (1)官网 (2) …

【算法设计zxd】第6章 回溯法

目录 6.1 回溯法的设计技术 : 四皇后问题 回溯法: 算法框架: 思考题: 回溯算法的适用条件 【例6-1】求满足下列不等式的所有整数解: 6.2回溯算法的经典例题 【例6-2】装载问题  问题分析 计算模型  算法设计与描…

网络安全常见问题隐患及其应对措施

随着数字化时代的到来,网络安全已经成为组织和个人面临的严重挑战之一。网络攻击日益普及,黑客和不法分子不断寻找机会侵入系统、窃取敏感信息、破坏服务和网络基础设施。在这种情况下,了解网络安全的常见问题隐患以及如何应对它们至关重要。…

Golang学习:基础知识篇(三)—— Map(集合)

Golang学习:基础知识篇(三)—— Map集合 前言什么是Golang?Map集合定义 Map综合实例补充 前言 很久之前就想学Go语言了,但是一直有其他东西要学,因为我学的是Java嘛,所以后面学的东西一直是跟J…