Как добавить валидацию csrf в пирамиду? - PullRequest
8 голосов
/ 22 июня 2011

Я передаю csrf_token для каждого сообщения и запроса xhr и хочу проверить токен по токену csrf сессии.Если они не совпадают, я выбрасываю 401.

Я использовал подписчика NewResponse в пирамиде для проверки запроса и проверки токена csrf в параметрах запроса относительно токена в сеансе.Проверка работает, но она по-прежнему вызывает представление, поэтому оно не работает должным образом.

Есть предложения о том, как это сделать?

@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 = []

Ответы [ 2 ]

9 голосов
/ 22 июня 2011

Абонент NewResponse называется после вашего просмотра.

Вы хотите использовать событие, которое вызывается ранее, например, NewRequest или ContextFound. В Pyramid 1.0 вам нужно будет использовать ContextFound для правильной обработки, потому что вы не можете вызывать исключения в NewRequest событиях (это исправлено в 1.1).

Способ сделать это с событием ContextFound - зарегистрировать представление исключений для объектов HTTPException, например:

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

По сути, это будет возвращать исключение в качестве объекта ответа при его поднятии, что совершенно верно для объектов HTTPException, которые являются действительными объектами Pyramid 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
0 голосов
/ 16 августа 2018

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)
...