Django 如何实现自定义权限控制

首先,需要安装相应的依赖包。在命令行中执行以下命令:

 
pip install django pip install djangorestframework pip install djangorestframework-simplejwt

然后,在 Django 的 settings.py 文件中添加以下配置:

 
REST_FRAMEWORK = { 'DEFAULT_AUTHENTICATION_CLASSES': ( 'rest_framework_simplejwt.authentication.JWTAuthentication', ), } SIMPLE_JWT = { 'ACCESS_TOKEN_LIFETIME': timedelta(hours=1), 'REFRESH_TOKEN_LIFETIME': timedelta(days=1), }

这里设置了 REST Framework 使用 JWTAuthentication 进行身份验证,以及 simpleJWT 的配置。

接下来,定义一个 Views,用于返回 JWT Token。我们将使用 Django 中的默认 User 模型和认证系统。在 views.py 文件中添加以下内容:

 
from rest_framework.views import APIView from rest_framework.response import Response from rest_framework_simplejwt.tokens import RefreshToken from django.contrib.auth import authenticate # 获取 Token API class TokenObtainView(APIView): def post(self, request, *args, **kwargs): # 获取用户名和密码 username = request.data.get('username') password = request.data.get('password') # 验证用户名和密码 user = authenticate(request, username=username, password=password) if user is None: return Response({'error': '用户名或密码错误'}) # 生成 JWT Token refresh = RefreshToken.for_user(user) return Response({ 'refresh': str(refresh), 'access': str(refresh.access_token), })

此处定义了一个 APIView,用于返回 JWT Token。首先从请求数据中获取用户名和密码,然后使用 authenticate() 方法验证用户。如果认证成功,就生成并返回 JWT Token。

最后,在 urls.py 文件中添加以下 URL 映射:

 
from django.urls import path from .views import TokenObtainView urlpatterns = [ path('api/token/', TokenObtainView.as_view(), name='token_obtain'), ]

这样,请求 /api/token/ 就会返回一个包含 Token 的 JSON 响应。

以上就是一个简单的 Django + simpleJWT 的集成示例。当然,在实际应用中,还需要对 views.py 文件进行更详细的编写,例如创建用户、获取用户信息等。

token 过期了如何刷新
token 过期了如何刷新

在 JWT Token 过期的情况下,客户端需要使用 Refresh Token 来刷新 Token。

通常情况下,客户端在登录成功后会收到两个 Token:Access Token 和 Refresh Token。Access Token 是用于身份验证的 Token,而 Refresh Token 则用于刷新 Access Token。

当 Access Token 过期时,客户端需要使用 Refresh Token 来向服务器请求一个新的 Access Token。在 simpleJWT 中,可以使用 Refresh Token 来刷新 Access Token。Refresh Token 的默认到期时间是 30 天,可以在配置中进行设置。

以下是使用 simpleJWT 刷新 Token 的一个示例:

 
from rest_framework_simplejwt.tokens import RefreshToken # 获取 Token 刷新 API class TokenRefreshView(APIView): def post(self, request, *args, **kwargs): # 获取 Refresh Token refresh = request.data.get('refresh') # 刷新 Access Token try: token = RefreshToken(refresh) return Response({ 'access': str(token.access_token), }) except TokenError as e: return Response({'error': str(e)})

在上述代码中,我们定义了一个 APIView 来刷新 Access Token。在请求数据中,我们获取了 Refresh Token,然后使用它来刷新 Access Token。

通过以上代码示例,我们可以了解到如何使用 simpleJWT 来刷新 Token。关键点是在 simpleJWT 中,我们可以使用 Refresh Token 来刷新 Access Token。在需要刷新 Token 的时候,客户端需要向服务器发送 Refresh Token,然后服务器就会使用它来生成新的 Access Token,并将其返回给客户端。

使用simple JWT 如何鉴定自定义权限呢
使用simple JWT 如何鉴定自定义权限呢

在 Django 中,可以使用自定义权限控制对 API 进行访问控制。在 simpleJWT 中,我们可以使用自定义 permissions 类来对 Access Token 进行鉴权。

以下是简单示例:

 
from rest_framework import permissions class IsAdminUser(permissions.BasePermission): """ 只允许管理员访问 """ def has_permission(self, request, view): return request.user and request.user.is_superuser class MyAPIView(APIView): permission_classes = [IsAdminUser] def get(self, request, *args, **kwargs): return Response({'message': '只有管理员可以访问'})

在上述代码中,我们首先定义了一个自定义权限类 IsAdminUser,继承自 permissions.BasePermission。在该类中,我们重写了 has_permission 方法,来验证 Access Token 中的用户是否是管理员。只有当用户是管理员时,该方法返回True,否则返回False。

在 MyAPIView 中,我们将权限类设置为 IsAdminUser。这样,当用户访问该 API 时,Django Rest Framework 会在执行视图方法之前先执行 IsAdminUser 的 has_permission 方法。只有当该方法返回 True 时,才会允许通过访问控制。

通过上述示例,我们可以实现自定义权限控制,来对 Access Token 进行鉴权。自定义权限控制是非常灵活的,可以根据不同的场景定义不同的权限类,从而实现精细化的访问控制。

如果是自定义的权限呢 比如说定义了好多组 每个组的权限都有不同 这个时候怎么鉴定权呢

如果您希望实现的是基于多个自定义权限组的权限检查,可以创建多个自权限,然后将这些权限类添加到 Django 视图的 permission_classes 属性。以下是一个示例:

首先,创建多个权限类。在这个例子中,我们假设有两个权限组:GroupA 和 GroupB,并根据用户的所属组确定他们的访问权限。

 
from rest_framework import permissions class GroupAPermission(permissions.BasePermission): """ 允许 GroupA 的用户访问 """ def has_permission(self, request, view): return request.user and request.user.groups.filter(name='GroupA').exists() class GroupBPermission(permissions.BasePermission): """ 允许 GroupB 的用户访问 """ def has_permission(self, request, view): return request.user and request.user.groups.filter(name='GroupB').exists()

然后,在视图中将这些权限类作为 permission_classes 的元素添加:

 
from rest_framework.views import APIView from rest_framework.response import Response class MyAPIView(APIView): permission_classes = [GroupAPermission, GroupBPermission] def get(self, request, *args, **kwargs): return Response({'message': 'GroupA 或者 GroupB 的用户可以访问此 API'})

在这个例子中,当用户访问 MyAPIView 时,Django Rest Framework 将会检查这个用户是否具有 GroupAPermission 或者 GroupBPermission。如果满足其中任意一个权限类的条件,那么用户将可以访问该 API。 用户需要至少属于 GroupA 或 GroupB 之一才可以访问该视图。

请注意,我们在这里给 permission_classes 提供了一个权限类列表。API 视图将根据列表中的任意一个权限类进行鉴权。你可以修改权限列表来为不同的视图控制不同的访问权限。

 
假设现在有个Group C 也想访问这个api 以后也会有group D, 我希望这个具有读权限的都可以访问 这个读权限我可以在后台分配 或者删除 来控制api 的访问限制

在这种情况下,您可以创建一个自定义权限类,并检查用户所属的任何组是否具有相应的权限。例如,您可以在 Django 后台为每个组定义一个具有读取权限(view 权限)的权限对象。然后,在自定义权限类中检查用户组是否具有此权限。

首先,在 models.py 文件中创建一个新的权限。例如,创建一个名为 APICanRead 的权限。为了更方便控制权限,我们可以将其附加到一个模型,例如一个名为 PermissionControl 的空模型:

 
from django.db import models class PermissionControl(models.Model): class Meta: permissions = [ ("APICanRead", "Can view API"), ] default_permissions = [] # 清空默认权限,以免混淆

接下来,在自定义权限类中检查用户所属的任何组是否具有这个权限:

 
from rest_framework import permissions class ApiReadPermission(permissions.BasePermission): """ 只允许具有读取权限的用户组访问。 """ def has_permission(self, request, view): # 检查用户所属的所有组是否具有"APICanRead"权限。 return ( request.user and request.user.groups.filter(permissions__codename="APICanRead").exists() )

现在,将 ApiReadPermission 类添加到您的 APIView:

 
from rest_framework.views import APIView from rest_framework.response import Response class MyAPIView(APIView): permission_classes = [ApiReadPermission] def get(self, request, *args, **kwargs): return Response({'message': '可以访问此 API 的用户组具有读权限'})

在这个示例中,我们首先创建了一个名为 APICanRead 的新权限,并将其附加到一个名为 PermissionControl 的模型。然后,我们在自定义权限类 ApiReadPermission 中检查用户所属的任何组是否具有此权限。最后,我们将此权限类添加到APIView。

现在,您可以在 Django 后台为不同的用户组分配或删除 APICanRead权限。只有具有此权限的用户组才能访问该 API。如果您需要添加新的组(如 GroupC、GroupD),只需在后台为新组分配 APICanRead 权限即可。这种方式使得权限管理变得更加灵活和可扩展。

 
posted @ 2023-06-11 19:06  skywss27  阅读(478)  评论(0编辑  收藏  举报