我正在为每个帖子和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 = []
答案 0 :(得分:9)
在调用视图后,NewResponse
订阅者称为。
您希望使用之前调用的事件,例如NewRequest
或ContextFound
。在Pyramid 1.0中,您需要使用ContextFound
来正确处理事情,因为您无法在NewRequest
事件中引发异常(这在1.1中已得到修复)。
使用ContextFound
事件执行此操作的方法是为HTTPException对象注册异常视图,如下所示:
config.add_view(lambda ctx, req: ctx, 'pyramid.httpexceptions.HTTPException')
基本上,这会在您引发异常时将异常作为响应对象返回,这对于作为有效金字塔Response
对象的HTTPException对象完全有效。
然后,您可以注册您的活动并处理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
答案 1 :(得分:0)