4

亲爱的 Stackoverflow 上的无所不知者,

在 Django 1.3 中,我正在制作一个 process_request 中间件,它从 url 获取令牌,将用户登录(如果正确)并从 url 中删除令牌。然而:

I) Django 建议不要在中间件中访问 POST/GET 数据,我不太确定为什么会这样……这同样适用于 request.path 吗?https://docs.djangoproject.com/en/dev/topics/http/middleware/#process-view

II)我想从 URL 中删除令牌,所以/album3/pic42/~53Cr3t70K3n/like/-> /album3/pic42/like/。但是更改 request.path 不起作用。找不到该页面,而

  • 中间件确实处理正确(通过打印验证)

  • 直接输入/album3/pic42/like/确实有效

  • 错误(带令牌)显示Request URL: http://www.site.com/album3/pic42/like/

有没有解决这个问题,或者我完全从错误的角度来解决这个问题?

提前致谢!

我刚刚意识到要改变它的客户端,显然我需要一个重定向(为什么我没有想到......)。但是,能够在没有新请求的情况下仅在服务器端重写它仍然很有用,例如访问个性化图像。


ps:如有需要,更多细节,请随意跳过

我正在开发一个(将)向用户发送个性化电子邮件的网站。我希望用户能够通过电子邮件链接中的令牌单击电子邮件中的链接并自动登录。这是对正常登录的补充。(我知道它不太安全,因为人们可能会转发电子邮件,但它对我的网站来说已经足够了)。url 看起来像这样:/album3/pic42/~53Cr3t70K3n/like/(去掉http ://www.site.com,Django 会这样做)

我正在编写一个中间件来匹配这个并在适当的时候让用户登录,一个用于接受令牌作为有效凭据的身份验证后端和一个令牌模型。


中间件 process_request 函数:def process_request(self, request):

    if '/~' in request.path:
        result = re.search('(.*)/~(.+?)/(.*)', request.path)
        (uidb36, token) = result.group(2).split('-', 2)
        user = authenticate(uidb36 = uidb36, token = token)
        if user: login(request, user)
        return HttpResponseRedirect('%s/%s' % (result.group(1), result.group(3)) + ('?' + '&'.join('='.join(item) for item in request.GET.items()) if request.GET else ''))
    return None

现在它适用于重定向,我也希望能够在内部进行。

4

2 回答 2

2

如果您不想弄乱上传处理程序,我有一个更好的解决方案给您:

  1. 在您的 urls.py 中创建一个规则来专门捕获带有令牌的访问

    将其放在开头urlpatterns以确保首先对其进行评估。这样的事情会做:

    (r'/~', 'my_app_name.my_redirect_view'),
    
  2. 创建一个视图

    def my_redirect_view(request):
        #Compiled regular expressions work much faster
        beloved_tokens = re.compile(r'(.*)/~(.+?)/(.*)')
        result = beloved_tokens.search(request.path)
        try:
            (uidb36, token) = result.group(2).split('-', 2)
            path_end = result.group(3)
        # We use "try" to be sure that no one had
        # messed with our beloved tokens:
        except AttributeError: 
            raise Http404
        else:
            user = authenticate(uidb36 = uidb36, token = token)
            if user: 
                login(request, user)
                return HttpResponseRedirect('%s/%s' % (result.group(1), result.group(3)) + ('?' + '&'.join('='.join(item) for item in request.GET.items()) if request.GET else ''))
            else:
                raise Http404
    
于 2011-11-06T20:47:54.447 回答
1

与访问 GET/POST 参数相比,IMO 更改 request.path 更糟糕(如果可以称为 bad),因此只需将令牌作为 GET 参数传递并基于令牌登录,不要重定向或进行 request.path 修改

我将令牌视为有效 url 的附加属性,因此中间件承认这一点并使用该令牌执行某些操作,但 url 仍然由正确的视图处理,所以中间件对我来说似乎非常合乎逻辑。

于 2011-11-06T21:05:41.753 回答