Python API 接口權限控制思路


需求:權限模塊對各子系統擁有動態配置權限的能力,發現接口變化能力,權限認證能力等,因為各子系統相互獨立,

所以需要使用統一的認證 JWT。

 

1、使用Django DRF權限模塊,進行修改

 1 import requests
 2 from config import AUTHENTICATE_URL
 3 from rest_framework import permissions
 4 from rest_framework.exceptions import PermissionDenied, AuthenticationFailed
 5 
 6 # URL(ViewSet) 權限配置
 7 URL_PERMISSION = {
 8     "pipelines": {
 9         "test_pipeline": "account.dev_audit",
10         "list": "account.test_audit",
11         "create": "account.yw_audit",
12         "retrieve": "",
13     },
14     # "sub_pipelines": {
15     #     "test_pipeline": "account.dev_audit",
16     #     "list": "account.test_audit",
17     #     "create": "account.yw_audit",
18     # }
19 }
20 
21 
22 class LoginPermission(permissions.BasePermission):
23     """
24     登錄驗證
25     """
26 
27     def has_permission(self, request, view):
28         # Read permissions are allowed to any request,
29         # so we'll always allow GET, HEAD or OPTIONS requests.
30         # print(request.method)
31         # if request.method == "POST":
32         #     return False
33         #
34         #     # 只有該snippet的所有者才允許寫權限。
35         # return False
36 
37         token = request.META.get("HTTP_AUTHORIZATION", "").replace("JWT ", '')
38         data = requests.post(AUTHENTICATE_URL + "/api/account/verify/", json={"token": token})
39         if data.status_code != 404:
40             raise AuthenticationFailed("登錄驗證失敗")
41         return True
42 
43 
44 class UrlPermission(permissions.BasePermission):
45     """
46     URL 權限驗證
47     """
48 
49     def has_permission(self, request, view):
50         # Read permissions are allowed to any request,
51         # so we'll always allow GET, HEAD or OPTIONS requests.
52         # print(request.method)
53         # if request.method == "POST":
54         #     return False
55         #
56         #     # 只有該snippet的所有者才允許寫權限。
57         # return False
58         token = request.META.get("HTTP_AUTHORIZATION", "").replace("JWT ", '')
59         print("==========通過視圖的basename,action進行權限認證==========")
60         print(view.basename, view.action)
61         print("==========")
62         if view.basename in URL_PERMISSION.keys():
63             if view.action in URL_PERMISSION[view.basename].keys():
64                 print(URL_PERMISSION[view.basename][view.action])
65                 data = requests.post(AUTHENTICATE_URL + "/api/account/verify/",
66                                      json={"token": token, "perm_code": URL_PERMISSION[view.basename][view.action]})
67                 if data.status_code != 404:
68                     raise PermissionDenied("訪問權限不合法")
69 
70         return True

 

2、設置權限全局生效

 

REST_FRAMEWORK = {
    # "DEFAULT_AUTHENTICATION_CLASSES": ["apps.permissions.Loginpermission", ]
    "DEFAULT_PERMISSION_CLASSES": [
        "apps.permissions.LoginPermission",
        "apps.permissions.UrlPermission",
    ]
}

 

如果需要局部權限,可以在相關視圖集(ViewSet)下增加自己的權限模塊

 

class PipelinesViewSet(BaseView):
    """
    流水線視圖
    """
    queryset = Pipelines.objects.filter(is_del=0).order_by("update_time")
    serializer_class = PipelinesSerializer
    filter_backends = (DjangoFilterBackend,)
    filter_fields = ('pipeline_name', 'pipeline_type')

    # permission_classes = ()  # 這里配置視圖權限

    @action(methods=['post'], detail=True, permission_classes=[])  #這里配置接口權限
    def test_pipeline(self, request, pk=None):
        """
        測試流水線接口
        """
        instance = self.get_object()
        serializer = self.get_serializer(instance)
        return Response(self.object_return(serializer.data))

 

3、權限系統統一獲取子系統接口,后期可以進行動態權限賦予

import coreapi

# Initialize a client & load the schema document
client = coreapi.Client()
schema = client.get("http://127.0.0.1:8000/docs/")

URL = []
# print(schema.data)
for basename, actions in schema.data.items():
    for action, atr in actions.links.items():
        URL_dict = {}
        URL_dict["basename"] = basename
        URL_dict["action"] = action
        URL_dict["method"] = atr.action
        URL_dict["url"] = atr.url
        URL_dict["description"] = atr.description
        URL.append(URL_dict)

for url in URL:
    print(url)

運行結果:這里收集視圖集中的base_name、action以及method,

對接口權限進行精確定位,不受url變化影響, 這里的url只做相關描述展示:

{'basename': 'pipelines', 'action': 'list', 'method': 'get', 'url': 'http://127.0.0.1:8000/apps/pipelines/', 'description': '流水線視圖'}
{'basename': 'pipelines', 'action': 'create', 'method': 'post', 'url': 'http://127.0.0.1:8000/apps/pipelines/', 'description': '流水線視圖'}
{'basename': 'pipelines', 'action': 'read', 'method': 'get', 'url': 'http://127.0.0.1:8000/apps/pipelines/{id}/', 'description': '流水線視圖'}
{'basename': 'pipelines', 'action': 'update', 'method': 'put', 'url': 'http://127.0.0.1:8000/apps/pipelines/{id}/', 'description': '流水線視圖'}
{'basename': 'pipelines', 'action': 'partial_update', 'method': 'patch', 'url': 'http://127.0.0.1:8000/apps/pipelines/{id}/', 'description': '流水線視圖'}
{'basename': 'pipelines', 'action': 'delete', 'method': 'delete', 'url': 'http://127.0.0.1:8000/apps/pipelines/{id}/', 'description': '流水線視圖'}
{'basename': 'pipelines', 'action': 'test_pipeline', 'method': 'post', 'url': 'http://127.0.0.1:8000/apps/pipelines/{id}/test_pipeline/', 'description': '測試流水線接口'}
{'basename': 'urlcollections', 'action': 'list', 'method': 'get', 'url': 'http://127.0.0.1:8000/apps/urlcollections/', 'description': ''}
{'basename': 'urlcollections', 'action': 'create', 'method': 'post', 'url': 'http://127.0.0.1:8000/apps/urlcollections/', 'description': ''}

 

前提:這里需要子系統開啟API接口文檔,通過接口文檔獲取接口詳情

 

from django.urls import path, include
from rest_framework.documentation import include_docs_urls

urlpatterns = [
    # path('admin/', admin.site.urls),
    path('docs/', include_docs_urls(title='API文檔', authentication_classes=[], permission_classes=[])),
    path('apps/', include('apps.urls')),
]

 

 

以上,大概可以符合需求,URL可以讀取接口導入權限系統,動態分配

 

java 也有比較好的接口權限細化管理的方案,如apache shiro.

 

  大神改進版 ,開源地址:https://gitee.com/tomsun28/bootshiro

 

還有的是casbin ,支持多種語言,github地址:https://github.com/casbin/pycasbin

 

但是這個也是針對於單個系統,如果需要對各個子系統進行接口權限控制,也是需要一番改造。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM