管理员模拟Django用户

2024-05-20 03:48:28 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个Django应用程序。当以管理员用户身份登录时,我希望能够在URL中传递一个秘密参数,并使整个站点的行为如同我是另一个用户一样。

假设我有一个URL/my-profile/,它显示了当前登录的用户配置文件。我想做一些类似/my-profile/?__user_id=123的事情,让底层视图相信我实际上是ID为123的用户(因此呈现用户配置文件)。

我为什么要那样?

只是因为它更容易重现某些只出现在单个用户帐户中的错误。

我的问题:

  1. 实现这样的东西最简单的方法是什么?

  2. 做这件事时,我应该考虑到什么安全问题吗?请注意,我(显然)只想为管理员用户提供此功能,而且我们的管理员用户可以完全访问源代码、数据库等。总之,这并不是真正的“后门”;它只是让访问用户帐户变得更容易。


Tags: django用户id应用程序url参数站点my
3条回答

看起来有相当多的人遇到了这个问题,并编写了可重用的应用程序来解决这个问题,至少有一些在django packages page for user switching中列出。写作时最活跃的似乎是:

  • django-hijack在管理员的用户列表中放置一个“劫持”按钮,同时在页面顶部放置一个位,以便您在劫持帐户时使用。
  • impostor意味着您可以使用用户名“me as other”和自己的密码登录
  • django-impersonate设置URL以开始模拟用户、停止、搜索等

我还没有足够的声誉来编辑或回复(我想),但我发现,虽然ionaut的解决方案在简单的情况下有效,但对我来说,一个更健壮的解决方案是使用会话变量。这样,即使AJAX请求也能得到正确的服务,而无需修改请求URL以包含GET模拟参数。

class ImpersonateMiddleware(object):
    def process_request(self, request):
        if request.user.is_superuser and "__impersonate" in request.GET:
            request.session['impersonate_id'] = int(request.GET["__impersonate"])
        elif "__unimpersonate" in request.GET:
            del request.session['impersonate_id']
        if request.user.is_superuser and 'impersonate_id' in request.session:
            request.user = User.objects.get(id=request.session['impersonate_id'])

用法:

log in: http://localhost/?__impersonate=[USERID]
log out (back to admin): http://localhost/?__unimpersonate=True

我用一个简单的中间件解决了这个问题。它还处理重定向(也就是说,在重定向期间保留GET参数)。这里是:

class ImpersonateMiddleware(object):
    def process_request(self, request):
        if request.user.is_superuser and "__impersonate" in request.GET:
            request.user = models.User.objects.get(id=int(request.GET["__impersonate"]))

    def process_response(self, request, response):
        if request.user.is_superuser and "__impersonate" in request.GET:
            if isinstance(response, http.HttpResponseRedirect):
                location = response["Location"]
                if "?" in location:
                    location += "&"
                else:
                    location += "?"
                location += "__impersonate=%s" % request.GET["__impersonate"]
                response["Location"] = location
        return response

相关问题 更多 >