成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專(zhuān)欄INFORMATION COLUMN

DRF | 針對(duì)指定的接口設(shè)置權(quán)限

用戶83 / 1654人閱讀

摘要:描述針對(duì)同一個(gè),對(duì)不同的接口設(shè)置不同的權(quán)限看了源碼通過(guò)源碼可以發(fā)現(xiàn),每次請(qǐng)求進(jìn)來(lái),都要做認(rèn)證,權(quán)限驗(yàn)證和限流驗(yàn)證。

描述

針對(duì)同一個(gè) view,對(duì)不同的接口設(shè)置不同的權(quán)限

看了 DRF views 源碼:

def initial(self, request, *args, **kwargs):
    """
    Runs anything that needs to occur prior to calling the method handler.
    """
    self.format_kwarg = self.get_format_suffix(**kwargs)

    # Perform content negotiation and store the accepted info on the request
    neg = self.perform_content_negotiation(request)
    request.accepted_renderer, request.accepted_media_type = neg

    # Determine the API version, if versioning is in use.
    version, scheme = self.determine_version(request, *args, **kwargs)
    request.version, request.versioning_scheme = version, scheme

    # Ensure that the incoming request is permitted
    self.perform_authentication(request)
    self.check_permissions(request)
    self.check_throttles(request)

通過(guò)源碼可以發(fā)現(xiàn),每次請(qǐng)求進(jìn)來(lái),都要做認(rèn)證,權(quán)限驗(yàn)證和限流驗(yàn)證。如果所有接口都需要權(quán)限,這直接在視圖類(lèi)中直接設(shè)置 permission_classes 即可;如果針對(duì)業(yè)務(wù)中部分接口需要權(quán)限,其他不需要權(quán)限的場(chǎng)景,這樣一刀切的方式是行不通的,因?yàn)檫M(jìn)來(lái)的請(qǐng)求會(huì)被權(quán)限打回去,針對(duì)部分接口需要權(quán)限的場(chǎng)景,可能需要變通一下。

1 場(chǎng)景如下:例如個(gè)人博客

例如有個(gè)分類(lèi)模型

class Category(models.Model):
    name = models.CharField("名稱(chēng)", max_length=30)
    created = models.DateTimeField("生成時(shí)間", auto_now_add=True)

    def __str__(self):
        return self.name

如果使用 DRF 的 viewset

class CategoryViewSet(viewsets.ModelViewSet):
    queryset = Category.objects.all()
    serializer_class = CategorySerializer

DRF 會(huì)自動(dòng)生成六個(gè)方法,具體就不說(shuō)了,對(duì)于個(gè)人博客來(lái)說(shuō),獲取列表以及詳情是不需要設(shè)置權(quán)限的,但是對(duì)于更新,創(chuàng)建,刪除時(shí)需要做權(quán)限驗(yàn)證的,那么問(wèn)題來(lái)了,我該怎么做好權(quán)限驗(yàn)證,這里我假使獲取詳情需要管理員權(quán)限,其他方法都不需要權(quán)限驗(yàn)證

2 變通方式 方法 1:自定義裝飾器

寫(xiě)包裝權(quán)限的裝飾器

from functools import update_wrapper

def wrap_permission(*permissions, validate_permission=True):
    """custom permissions for special route"""
    def decorator(func):
        def wrapper(self, request, *args, **kwargs):
            self.permission_classes = permissions
            if validate_permission:
                self.check_permissions(request)
            return func(self, request, *args, **kwargs)
        return update_wrapper(wrapper, func)
    return decorator

自定義權(quán)限類(lèi)

from rest_framework.permissions import IsAdminUser

class IsVbAdminUser(IsAdminUser):
    """
    Allows access only to admin users.
    """
    def has_object_permission(self, request, view, obj):
        """
        Return `True` if permission is granted, `False` otherwise.
        """
        return self.has_permission(request, view)

然后在 viewset 中,例如獲取詳情接口,這樣用,

@wrap_permission(IsVbAdminUser)
def retrieve(self, request, *args, **kwargs):

如果直接請(qǐng)求,就會(huì)下面錯(cuò)誤

"error_message": "Authentication credentials were not provided."

后面在 DRF 的裝飾器中找到 permission_classes

def permission_classes(permission_classes):
    def decorator(func):
        func.permission_classes = permission_classes
        return func
    return decorator

這個(gè)默認(rèn)的業(yè)務(wù)還需要定制,根據(jù)自己業(yè)務(wù)需要了

方法2:使用 detail_route 或者 list_route
@detail_route(
    url_path="test",
    permission_classes=(IsVbAdminUser, ),
)
def test(self, request, *args, **kwargs):

這樣耍的原因,在看了 DRF route 源代碼,發(fā)現(xiàn)

method_kwargs = getattr(viewset, methodname).kwargs
initkwargs = route.initkwargs.copy()
initkwargs.update(method_kwargs)

是不是很好玩

對(duì)于自定義路由,使用這種方法,還是蠻方便的。

方法 3:重新定義 initial 方法

重寫(xiě) initial 方法,根據(jù)方法定義不同的權(quán)限類(lèi)

添加 permission_classes_map 類(lèi)屬性

permission_classes_map 定義接口和權(quán)限的映射,用法如下:

permission_classes_map = {
    方法名: 權(quán)限類(lèi)列表
}

此為特定接口的權(quán)限檢測(cè),例如如果視圖中包含 create 方法,同時(shí)在又在視圖中設(shè)置了全局性的 permission_classes,
但是想為 create 定義不同于全局的權(quán)限,所以這里可以這樣設(shè)置,示例如下:

permission_classes_map = {
    "create": [CustomPermission]
}
permission_classes_map = {}

def initial(self, request, *args, **kwargs):
    """重新定義此方法,添加靈活配置權(quán)限映射"""
    if request.method.lower() in self.http_method_names:
        handler = getattr(self, request.method.lower(), self.http_method_not_allowed)
    else:
        handler = self.http_method_not_allowed

    if hasattr(handler, "__name__"):
        handler_name = handler.__name__
    elif hasattr(handler, "__func__"):
        handler_name = handler.__func__.__name__
    else:
        handler_name = None

    if handler_name and handler_name in self.permission_classes_map:
        if isinstance(self.permission_classes_map.get(handler_name), (tuple, list)):
            self.permission_classes = self.permission_classes_map.get(handler_name)
    return super(CommonWithSignViewSet, self).initial(request, *args, **kwargs)
方法 4:使用不同的視圖

把需要權(quán)限驗(yàn)證的和不需要權(quán)限驗(yàn)證的視圖分開(kāi),寫(xiě)兩個(gè)視圖,但是這樣做會(huì)冗余部分代碼

3 小結(jié)

我在以往的經(jīng)歷中,如果是針對(duì)默認(rèn)的路由需要加權(quán)限驗(yàn)證,我會(huì)使用方法 1,對(duì)于自定義路由,我會(huì)使用方法 2,當(dāng)然也可以反過(guò)來(lái)思考,設(shè)置全局的權(quán)限驗(yàn)證,如果那個(gè)方法不需要權(quán)限驗(yàn)證,使用裝飾器把權(quán)限設(shè)置為空即可,隨便怎么折騰

前兩種方法盡量不要再視圖屬性中設(shè)置 permission_classes,這樣的處理有點(diǎn)奇葩,個(gè)人可以針對(duì) DRF 處理流程,進(jìn)行包裝,看業(yè)務(wù)需要。

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/44331.html

相關(guān)文章

  • DRF | 針對(duì)指定接口設(shè)置權(quán)限

    摘要:描述針對(duì)同一個(gè),對(duì)不同的接口設(shè)置不同的權(quán)限看了源碼通過(guò)源碼可以發(fā)現(xiàn),每次請(qǐng)求進(jìn)來(lái),都要做認(rèn)證,權(quán)限驗(yàn)證和限流驗(yàn)證。 描述 針對(duì)同一個(gè) view,對(duì)不同的接口設(shè)置不同的權(quán)限 看了 DRF views 源碼: def initial(self, request, *args, **kwargs): Runs anything that needs to occur pr...

    TANKING 評(píng)論0 收藏0
  • DRF | 針對(duì)指定接口設(shè)置權(quán)限

    摘要:描述針對(duì)同一個(gè),對(duì)不同的接口設(shè)置不同的權(quán)限看了源碼通過(guò)源碼可以發(fā)現(xiàn),每次請(qǐng)求進(jìn)來(lái),都要做認(rèn)證,權(quán)限驗(yàn)證和限流驗(yàn)證。 描述 針對(duì)同一個(gè) view,對(duì)不同的接口設(shè)置不同的權(quán)限 看了 DRF views 源碼: def initial(self, request, *args, **kwargs): Runs anything that needs to occur pr...

    gplane 評(píng)論0 收藏0
  • Django-緩存

    摘要:自帶了一個(gè)健壯的緩存系統(tǒng)來(lái)保存動(dòng)態(tài)頁(yè)面,避免每次請(qǐng)求都重新計(jì)算。緩存中的和方法是很常見(jiàn)的。盡量放在第一個(gè)繼承的類(lèi)設(shè)置過(guò)期時(shí)間根據(jù)自己需求加緩存。目前這個(gè)緩存使用的是內(nèi)存。 概述:對(duì)于中等流量的網(wǎng)站來(lái)說(shuō),盡可能的減少開(kāi)銷(xiāo)是非常必要的。緩存數(shù)據(jù)就是為了保存那些需要很多計(jì)算資源的結(jié)果,這樣的話就不必在下次重復(fù)消耗計(jì)算資源。獲取數(shù)據(jù)的數(shù)據(jù)的時(shí)候就是去緩存中拿,拿到了直接返回,沒(méi)拿到就去數(shù)據(jù)庫(kù)中...

    aervon 評(píng)論0 收藏0
  • 記錄django-rest-framework處理微信支付notify_url遇到問(wèn)題

    摘要:微信支付統(tǒng)一下單接口,有一個(gè)叫的參數(shù),作用我就照搬官方文檔異步接收微信支付結(jié)果通知的回調(diào)地址,通知必須為外網(wǎng)可訪問(wèn)的,不能攜帶參數(shù)。 最近在做一個(gè)小程序,小程序有涉及到微信支付,說(shuō)來(lái)慚愧,還是第一次自己動(dòng)手去做微信支付這一塊的實(shí)現(xiàn),所以過(guò)程中遇到了很多人都會(huì)踩的坑(例如mmp的微信支付各種key各種id要在哪里找,很難找),這次使用django來(lái)開(kāi)發(fā),接口部分用django-rest-...

    NicolasHe 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<