【问题标题】:In Django, how to set value in request object in decorator function and access it from request object in decorated function在 Django 中,如何在装饰函数中的请求对象中设置值并从装饰函数中的请求对象访问它
【发布时间】:2020-06-25 11:00:51
【问题描述】:

我已经使用 django 实现了后端 api。环境细节如下-

环境: 平台:Linux(ubuntu) 框架:Django 1.11.28 编程语言:python 2.7.12(未来计划迁移3.8) 数据库:MongoDB 3.4

说明: 我已经使用 django 开发了 Web 服务。这些是普通的 Web 服务,不是 Restful(之前没有完全支持 Django REST 框架的 mongodb),因此大多数东西不是按照 django 标准定制的。

问题详情: 对于身份验证,我使用的是 Azure AD。我编写了简单的装饰器,它从前端 Web 应用程序/移动设备发送的请求中接收访问令牌,然后这个装饰器验证令牌并返回查看。对于身份验证,我使用 django-auth-adfs 包

装饰器

授权.py

def is_authorized(function):
    @wraps(function)
    def authorize(request, *args, **kwargs):
        # access token validation logic
        if validated(token):
            # get user details from access token first_name, last_name etc
            user_info = {"first_name":"foo","last_name":"bar"}
            return function(request, *args, **kwargs)
        else:
            return HttpResponse('Unauthorized', status=401)
return authorize

查看.py

@is_authorized
def home_view(request):
    # calling function which decodes access token and return user details.
    # This function contains same code as in decorator except function it returns user_info
    **first_name, last_name = get_userinfo_from_access_token(request)**
return JsonResponse({"data":{"fname":first_name,"lname":last_name}})

如您所见,代码变得混乱且重复。在此视图中,我无法访问已在视图中解码的用户详细信息。为了获取用户详细信息,我通过传递请求对象在 get_userinfo_from_access_token() 函数中编写了相同的代码,我认为这不是“好的”。

  • 我需要符合 django 标准的方法,并且大多数 django 开发人员都遵循该方法。我是否需要实现一些身份验证后端或一些 django 中间件,如果是,请指导我完成它。

考虑到我目前的场景和环境,

  1. 您能否解释一下从请求对象访问用户详细信息的最佳和标准方法
  2. 我创建了很多视图,我正在为每个视图添加 is_authorized 装饰器。是否有任何标准和更好的方法来保护视野。
  3. 我计划在未来使用 django rest 框架重写整个代码。如果有人为我提供一些参考或指南来实现宁静的 Web 服务,我将非常感激,这样我就可以使用我现有的代码并减少我的工作量。

如果我有任何不清楚的地方和需要的更多详细信息,请告诉我。 提前致谢。

【问题讨论】:

    标签: python django django-rest-framework django-authentication django-middleware


    【解决方案1】:

    嗯。让我依次给出你的答案。

    1. 编写中间件并根据数据库查询中的令牌附加用户。
    2. 创建另一个中间件,仅当用户通过上述 (1) 中间件进行身份验证时才允许受保护的路径。
    3. 由于 django 每天都在变化,最好在何时在 REST 上实现时提出单独的问题。我知道标准,但现在回答它可能会在以后过时。

    现在回到中间件。 中间件按顺序工作。无效的顺序可能不起作用

    第一个中间件

    class UserResolverMiddleware(MiddlewareMixin):
        """
        A middleware class that adds a ``user`` attribute to the current request.
        """
    
        def process_request(self, request):
            """
    
            get token from request header
            validate token
            decode the token
            query on db or attach a fake user with necessary decoded data. 
            attach user object to request like request.user = user
            """
    

    第二个。

    from django.http import HttpResponseForbidden
    class ProtectedViewMiddleware(MiddlewareMixin):
    
    
        def process_request(self, request):
    
            """
            create a list of URL which is not protected (e.g: login, forget password)
            unprotected_list = ['']
            if request url does not belongs to unprotected_list and request has no attribue user:
    
                return  HttpResponseForbidden()
            return 
            """
    

    【讨论】:

    • 感谢您的回复。您能否详细说明需要第二个中间件,如果我不使用第二个中间件会怎样,这会如何影响我的安全性。
    • 第二个中间件作为 is_authorized 装饰器工作。如果用户未经过身份验证但想在受保护的视图中访问,我们只是忽略它们。如果您不使用此中间件,则必须在每个受保护的视图中处理身份验证。
    • 我可以将排除的 url 放在与 1 中提到的相同的中间件中,并且不会处理令牌身份验证。但是,如果我编写另一个中间件,请纠正我,它不会在第一个中间件之后执行。因此,对于未经身份验证的用户访问的视图将不起作用。
    • 您能否提供上述第二个中间件的示例,它将更加清楚并帮助我理解。现在我能够实现预期的目标,但我想遵循标准方法。在此之后,我可以将其标记为我的查询的答案。
    • @sachin27,请看一下
    猜你喜欢
    • 2012-08-06
    • 1970-01-01
    • 1970-01-01
    • 2017-10-13
    • 1970-01-01
    • 2020-12-12
    • 2020-11-04
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多