src/pyams_security/csrf.py
changeset 97 e3f804db3e6f
equal deleted inserted replaced
96:8e65d6c0d95a 97:e3f804db3e6f
       
     1 #
       
     2 # Copyright (c) 2008-2015 Thierry Florac <tflorac AT ulthar.net>
       
     3 # All Rights Reserved.
       
     4 #
       
     5 # This software is subject to the provisions of the Zope Public License,
       
     6 # Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
       
     7 # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
       
     8 # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
       
     9 # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
       
    10 # FOR A PARTICULAR PURPOSE.
       
    11 #
       
    12 
       
    13 __docformat__ = 'restructuredtext'
       
    14 
       
    15 
       
    16 # import standard library
       
    17 
       
    18 # import interfaces
       
    19 from pyramid.interfaces import INewRequest, INewResponse
       
    20 
       
    21 # import packages
       
    22 from pyramid.events import subscriber
       
    23 from pyramid.exceptions import BadCSRFToken
       
    24 from pyramid.session import check_csrf_origin
       
    25 from pyramid.util import strings_differ
       
    26 
       
    27 
       
    28 CSRF_TOKEN_COOKIE_NAME = 'csrf_token'
       
    29 
       
    30 
       
    31 @subscriber(INewRequest)
       
    32 def handle_new_request(event):
       
    33     """Handle any request with CSRF token cookie"""
       
    34     request = event.request
       
    35     if (request.method == 'POST') or request.is_xhr:
       
    36         check_csrf_origin(request)
       
    37         post_token = request.cookies.get(CSRF_TOKEN_COOKIE_NAME)
       
    38         session_token = request.session.get_csrf_token()
       
    39         if (not post_token) or strings_differ(post_token, session_token):
       
    40             raise BadCSRFToken('Invalid CSRF token')
       
    41 
       
    42 
       
    43 @subscriber(INewResponse)
       
    44 def handle_new_response(event):
       
    45     """Handle new response to manage CSRF token cookie"""
       
    46     request = event.request
       
    47     if not request.path.startswith('/--static--/'):
       
    48         token = request.session.get_csrf_token()
       
    49         event.response.set_cookie(CSRF_TOKEN_COOKIE_NAME, token,
       
    50                                   secure=request.scheme == 'https',
       
    51                                   httponly=True)