8

すべての投稿とxhrリクエストに対してcsrf_tokenを渡し、セッションcsrfトークンに対してトークンを検証したいと思います。それらが一致しない場合、私は401を投げます。

ピラミッドのNewResponseサブスクライバーを使用して、リクエストを検査し、リクエストパラメーターのcsrfトークンをセッションのトークンと照合して検証しました。検証は機能しますが、それでもビューを呼び出すため、defは正常に機能しません。

これを行うための適切な方法に関する提案はありますか?

@subscriber(NewResponse)
def new_response(event):
    """Check the csrf_token if the user is authenticated and the 
    request is a post or xhr req.
    """
request = event.request
response = event.response
user = getattr(request, 'user', None)
# For now all xhr request are csrf protected.
if (user and user.is_authenticated()) and \
   (request.method == "POST" or request.is_xhr) and \
    (not request.params.get('csrf_token') or \
    request.params.get('csrf_token') != unicode(request.session.get_csrf_token())):
    response.status = '401 Unauthorized'
    response.app_iter = []
4

2 に答える 2

9

ビューが呼び出された後NewResponseサブスクライバーが呼び出されます。

たとえばNewRequest、またはなど、以前に呼び出されたイベントを使用する必要がありますContextFound。Pyramid 1.0では、イベントContextFoundで例外を発生させることができないため、を使用して適切に処理する必要がありNewRequestます(これは1.1で修正されています)。

イベントでこれを行う方法は、ContextFound次のようなHTTPExceptionオブジェクトの例外ビューを登録することです。

config.add_view(lambda ctx, req: ctx, 'pyramid.httpexceptions.HTTPException')

基本的に、これは例外を発生させたときに応答オブジェクトとして例外を返します。これは、有効なPyramidオブジェクトであるHTTPExceptionオブジェクトに対して完全に有効ですResponse

次に、イベントを登録して、CSRF検証を処理できます。

@subscriber(ContextFound)
def csrf_validation_event(event):
    request = event.request
    user = getattr(request, 'user', None)
    csrf = request.params.get('csrf_token')
    if (request.method == 'POST' or request.is_xhr) and \
       (user and user.is_authenticated()) and \
       (csrf != unicode(request.session.get_csrf_token())):
        raise HTTPUnauthorized
于 2011-06-22T15:59:19.207 に答える
1

Pyramidには独自のCSRF検証が含まれていますが、これはおそらくより良い選択です。

セッションにCSRFトークンが保存されている場合、これにより次の構成になります。

from pyramid.csrf import SessionCSRFStoragePolicy

def includeme(config):
    # ...
    config.set_csrf_storage_policy(SessionCSRFStoragePolicy())
    config.set_default_csrf_options(require_csrf=True)
于 2018-08-16T14:16:06.533 に答える