【问题标题】:remove authentication and permission for specific url path删除特定 url 路径的身份验证和权限
【发布时间】:2020-06-25 05:32:20
【问题描述】:

我正在与 DRF 合作并遇到了这个问题。我有一个第三方视图,我将其导入到我的urls.py 文件中,如下所示:

from some_package import some_view

urlpatterns = [
    path('view/',some_view)
]

但我面临的问题是因为我在settings.py 中启用了默认权限类,如下所示:

REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': (
               'rest_framework.authentication.TokenAuthentication',
    ),
    'DEFAULT_PERMISSION_CLASSES':(
                'rest_framework.permissions.IsAuthenticated',
    ),

}

现在当我使用 url 调用该视图时,它给了我 authentication error 因为我 不提供令牌。有没有办法可以绕过身份验证错误而不必须直接在视图中进行更改,我知道我们可以删除该特定视图的权限,但为此我必须更改 some_view 功能代码。但我不想这样做,假设我们无权访问该功能,我们只能传递数据并接收响应。如何绕过身份验证而不必更改该功能代码。 我尝试搜索,但找不到我要找的东西。

我假设我们可以通过 urls.py 以某种方式做到这一点,例如指定任何参数或类似的东西,使特定视图绕过身份验证而无需更改函数代码。

类似这样的:

from some_package import some_view

    urlpatterns = [
        path('view/',some_view,"some_parameter") #passing someparameter from here or something like that
    ]

这可能是我正在寻找的吗?在此先感谢:)

【问题讨论】:

  • 我不知道有什么方法可以做到这一点。你最好的办法是包装视图(即编写你自己的)并设置authentication_classes。这对你有用吗?
  • 您也可以删除DEFAULT_AUTHENTICATION_CLASSESDEFAULT_PERMISSION_CLASSES 并将其移动到您自己的父类中进行身份验证和授权,然后在您的视图中继承它。那么您的第三方视图将不会默认为您在 settings.py 中提供的内容,因为您没有提供任何内容。
  • 是的,我可以这样做,但这会导致进行更多更改,而不是执行您建议的操作,最好覆盖该函数并为覆盖函数指定authentication_classes,然后调用原始函数从那个被覆盖的函数。 @yvesonline
  • 这就是我的第一条评论的意思。老实说,如果您要导入的只是一个视图,我认为这是要走的路。
  • 我已经尝试过这种覆盖方式。对我来说效果很好。这样做是个好主意。我很久以前就做过了。

标签: python django django-rest-framework django-rest-auth django-rest-framework-simplejwt


【解决方案1】:

因此,第三方视图最合适的方式是通过在 urls.py 中定义装饰器来使用装饰器:

案例一

我假设some_view 是一个继承自rest_framework.views.APIView 的类:

urls.py

from django.urls import path
from rest_framework.decorators import permission_classes, authentication_classes
from rest_framework.permissions import AllowAny

from some_package import some_view

urlpatterns = [
    path('', authentication_classes([])(permission_classes([AllowAny])(some_view)).as_view())
]

案例2

我假设some_view是一个简单的Django视图函数,你需要为GET方法定义它:

urls.py

from django.urls import path
from rest_framework.decorators import api_view, permission_classes, authentication_classes
from rest_framework.permissions import AllowAny

from some_package import some_view

urlpatterns = [
    path('', api_view(['GET'])(authentication_classes([])(permission_classes([AllowAny])(some_view))))
]

案例3

我假设 some_view 是一个 api_view 装饰的 DRF 视图函数。这是最难的也是最不可能的部分,因为你必须取消之前的api_view 装饰器的装饰。如果视图函数用api_view装饰,那么它已经被转换为Django视图函数,所以permision_classesauthentication_classes都不能附加到类:

【讨论】:

    【解决方案2】:

    你没试过吗:

    from rest_framework.permissions import AllowAny
    from rest_framework.decorators import authentication_classes, permission_classes
    
    @authentication_classes((AllowAny, ))
    @permission_classes((AllowAny, ))
    def method()
    

    【讨论】:

    • 对我来说,这个方法根本行不通
    【解决方案3】:

    您可以覆盖默认身份验证类以跳过特定 url 的身份验证。

    例如:

    class CustomIsAuthenticated(IsAuthenticated):
    
        def has_permission(self, request, view):
            # make a list of public urls
            if request.path in PUBLIC_URLS:
                return True
            return super().has_permission(request, view)
    

    您必须创建一个绕过身份验证的PUBLIC_URLS 列表。

    现在在rest框架设置中的DEFAULT_PERMISSION_CLASSES中使用这个类。并删除默认的IsAuthenticated 类。

    虽然我推荐使用装饰器的方法。 查看文档:https://www.django-rest-framework.org/api-guide/permissions/#allowany

    装饰器方法更冗长,通过查看函数,您可以判断它是否公开。

    【讨论】:

      【解决方案4】:

      @Bedilbek 的回答对我有用,但如果您希望使用不同的语法并在视图中定义 permission_classesauthentication_classes 而不是 urls.py,您可以执行以下操作:

      from rest_framework import permissions
      from rest_framework.views import APIView
      
      class SomeView(APIView):
          permission_classes = [permissions.AllowAny]
          authentication_classes = []
      

      【讨论】:

        猜你喜欢
        • 2018-03-31
        • 1970-01-01
        • 1970-01-01
        • 2021-03-10
        • 2012-12-02
        • 1970-01-01
        • 1970-01-01
        • 2016-04-20
        • 2016-05-30
        相关资源
        最近更新 更多