我正在尝试做一个中间件,它可以根据子域等为用户更改一些字段。
唯一的问题是请求。user在中间件中总是以AnonymousUser的形式出现,但在视图中却是正确的用户。我在设置中保留了django使用的默认认证和会话中间件。
这里有一个类似的问题:Django, request.user is always Anonymous User但这并没有完全回答问题,因为我没有使用不同的身份验证方法,并且djangos身份验证在我调用自己的中间件之前运行。
在使用DRF时,是否有一种方法可以在中间件中获取request.user?
class SampleMiddleware(object):
def process_view(self, request, view_func, view_args, view_kwargs):
#This will be AnonymousUser. I need it to be the actual user making the request.
print (request.user)
def process_response(self, request, response):
return response
使用进程请求:
class SampleMiddleware(object):
def process_request(self, request):
#This will be AnonymousUser. I need it to be the actual user making the request.
print (request.user)
def process_response(self, request, response):
return response
8条答案
按热度按时间fwzugrvs1#
我已经解决了这个问题,方法是从请求中获取DRF令牌,并将request.user加载到与该模型关联的用户。
我有默认的django认证和会话中间件,但DRF似乎在中间件之后使用它的令牌认证来解析用户(所有请求都是CORS请求,这可能是原因)。
这也可以用在process_view或process_request上。
希望这能在未来帮助到一些人。
e3bfsja22#
今天遇到这个,同时也有同样的问题。
跳过下面的代码示例
问题是DRF有自己的东西流,就在django请求life-cycle的中间。
因此,如果正常的中间件流程是:
1.模板_中间件(渲染前)
DRF代码,覆盖默认的django视图代码,并执行自己的代码。
在上面的链接中,您可以看到它们用自己的方法 Package 原始请求,其中一个方法是DRF身份验证。
回到你的问题,这就是为什么在中间件中使用
request.user
还为时过早,因为它只有在view_middleware执行之后才能得到它的值。我采用的解决方案是让我的中间件设置一个
LazyObject
。这很有帮助,因为我的代码(实际的DRF ApiVIEw)在实际用户已经通过DRF的身份验证设置时执行。如果DRF有更好的方法来扩展它们的功能,可能会更好,但就目前情况而言,这似乎比提供的解决方案更好(性能和可读性方面)。
jdgnovmf3#
accepted answer只考虑
TokenAuthentication
-在我的例子中,配置了更多的认证方法,因此我直接初始化DRF的Request
,调用DRF的认证机制并循环所有配置的认证方法。不幸的是,由于必须查询
Token
对象,因此它仍然会给数据库带来额外的负载(公认的答案也有这个问题)。在this answer中使用SimpleLazyObject
的技巧是一个好得多的解决方案,但它不适合我的用例,因为我需要中间件中的用户信息-我M扩展X1 E2 F1 X中的度量,并且它在调用X1 M5 N1 X之前处理该请求。oogrdqng4#
基于上面丹尼尔Dubovski非常优雅的解决方案,这里有一个Django 1.11中间件的例子:
6psbrbz95#
Daniel Dubovski's solution在大多数情况下可能是最好的。
惰性对象方法的问题在于是否需要依赖副作用。在我的例子中,我需要对每个请求都发生一些事情,无论什么。
如果我使用
request.custom_prop
这样的特殊值,那么必须为每个请求计算它,才能产生副作用。我注意到其他人正在设置request.user
,但它对我不起作用,因为一些中间件或身份验证类覆盖了这个属性。如果DRF支持它自己的中间件呢?我可以在哪里插入它?在我的例子中(我不需要访问
request
对象,只需要访问经过身份验证的用户),最简单的方法似乎是挂钩到身份验证类本身:然后我可以在我的设置中替换这一行:
我不是在推广这个解决方案,但也许它会帮助别人。
d6kp6zgx6#
我知道这并没有完全回答“我们能从中间件访问它吗”的问题,但我认为这是一个更优雅的解决方案,而不是在中间件中做同样的工作,而不是DRJ在其基视图类中做同样的工作。
基本上,我只是覆盖了DRF代码中的方法'perform_authentication()',因为我需要在请求中添加更多与当前用户相关的内容。
之后,在您自己的视图中,不要将来自DRF的APIView设置为父类,只需将该类设置为父类即可。
ckocjqey7#
我对现有的解决方案不是很满意。这里有一个解决方案,它使用一些DRF内部机制来确保在中间件中应用了正确的身份验证,即使视图有特定的权限类。它使用中间件钩子
process_view
,让我们可以访问将要访问的视图:请注意,这并不能避免两次认证,DRF仍然会很乐意在认证后立即进行认证。
hmae6n7t8#
我也遇到了同样的问题,决定改变我的设计,我没有使用中间件,而是简单地用猴子补丁
rest_framework.views.APIView
。在我的例子中,我需要修补
check_permissions
,但你可以修补任何适合你的问题。看看the source code。myapp/patching.py