Как добавить проверку csrf в pyramid?
Я передаю csrf_token для каждого запроса post и xhr и хочу проверить токен против токена 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 = []
2 ответов
на 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
пирамида содержит собственная проверка CSRF, что, вероятно, лучший выбор.
учитывая, что в вашем сеансе хранятся токены CSRF, это приведет к следующей конфигурации:
from pyramid.csrf import SessionCSRFStoragePolicy
def includeme(config):
# ...
config.set_csrf_storage_policy(SessionCSRFStoragePolicy())
config.set_default_csrf_options(require_csrf=True)