如何将csrf验证添加到金字塔?

时间:2011-06-22 03:21:57

标签: python pyramid

我正在为每个帖子和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 = []

2 个答案:

答案 0 :(得分:9)

在调用视图后,NewResponse订阅者称为

您希望使用之前调用的事件,例如NewRequestContextFound。在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)

金字塔包含其own CSRF validation,这可能是一个更好的选择。

鉴于您的会话存储了CSRF令牌,这将导致以下配置:

createDirectory