4

Stackoverflow の全知全能の皆様へ

Django 1.3 では、URL からトークンを取得し、(正しい場合) ユーザーをログインさせ、URL からトークンを削除する process_request ミドルウェアを作成しています。でも:

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

IMO の request.path の変更は、GET/POST パラメータへのアクセスに比べて(悪いと言える場合)より悪いため、トークンを GET パラメータとして渡し、トークンに基づいてログインし、request.path の変更をリダイレクトしたり実行したりしないでください。

トークンは有効な URL に追加された属性と見なされるため、ミドルウェアはそれを認識し、そのトークンで何かを行いますが、URL は依然として正しいビューによって処理されるため、ここではミドルウェアが非常に論理的に適合するように思えます。

于 2011-11-06T21:05:41.753 に答える