Update flask_wtf to 0.14.2 and make CSRFProtect available to current_app

By default CSRF protection is disabled for all views, since most
web endpoints and all API endpoints do not need it.
On the views that require it, we use the 
current_app.csrf.protect() method.
This commit is contained in:
Francesco Siddi 2018-03-28 22:05:54 +02:00
parent fc9c518c2a
commit e69f991aa6
6 changed files with 24 additions and 6 deletions

View File

@ -73,6 +73,7 @@ class PillarServer(BlinkerCompatibleEve):
def __init__(self, app_root, **kwargs): def __init__(self, app_root, **kwargs):
from .extension import PillarExtension from .extension import PillarExtension
from celery import Celery from celery import Celery
from flask_wtf.csrf import CSRFProtect
kwargs.setdefault('validator', custom_field_validation.ValidateCustomFields) kwargs.setdefault('validator', custom_field_validation.ValidateCustomFields)
super(PillarServer, self).__init__(settings=empty_settings, **kwargs) super(PillarServer, self).__init__(settings=empty_settings, **kwargs)
@ -141,6 +142,10 @@ class PillarServer(BlinkerCompatibleEve):
self.before_first_request(self.setup_db_indices) self.before_first_request(self.setup_db_indices)
# Make CSRF protection available to the application. By default it is
# disabled on all endpoints. More info at WTF_CSRF_CHECK_DEFAULT in config.py
self.csrf = CSRFProtect(self)
def _validate_config(self): def _validate_config(self):
if not self.config.get('SECRET_KEY'): if not self.config.get('SECRET_KEY'):
raise ConfigurationMissingError('SECRET_KEY configuration key is missing') raise ConfigurationMissingError('SECRET_KEY configuration key is missing')

View File

@ -255,3 +255,8 @@ SEND_FILE_MAX_AGE_DEFAULT = 3600 * 24 * 365 # seconds
# be used. Note that this causes extra traffic, since every time the process # be used. Note that this causes extra traffic, since every time the process
# restarts the URLs will be different. # restarts the URLs will be different.
STATIC_FILE_HASH = '' STATIC_FILE_HASH = ''
# Disable default CSRF protection for all views, since most web endpoints and
# all API endpoints do not need it. On the views that require it, we use the
# current_app.csrf.protect() method.
WTF_CSRF_CHECK_DEFAULT = False

View File

@ -487,9 +487,8 @@ def preview_markdown():
content of a node. content of a node.
""" """
if not validate_csrf(request.headers.get('X-CSRFToken')): current_app.csrf.protect()
return jsonify({'_status': 'ERR',
'message': 'CSRF validation failed.'}), 403
try: try:
content = request.form['content'] content = request.form['content']
except KeyError: except KeyError:

View File

@ -16,7 +16,7 @@ Flask-Babel==0.11.2
Flask-Cache==0.13.1 Flask-Cache==0.13.1
Flask-Script==2.0.6 Flask-Script==2.0.6
Flask-Login==0.3.2 Flask-Login==0.3.2
Flask-WTF==0.12 Flask-WTF==0.14.2
gcloud==0.12.0 gcloud==0.12.0
google-apitools==0.4.11 google-apitools==0.4.11
httplib2==0.9.2 httplib2==0.9.2

View File

@ -39,7 +39,7 @@ setuptools.setup(
'Flask-Script>=2.0.5', 'Flask-Script>=2.0.5',
'Flask-Login>=0.3.2', 'Flask-Login>=0.3.2',
'Flask-OAuthlib>=0.9.3', 'Flask-OAuthlib>=0.9.3',
'Flask-WTF>=0.12', 'Flask-WTF>=0.14.2',
'algoliasearch>=1.12.0', 'algoliasearch>=1.12.0',
# Limit the major version to the major version of ElasticSearch we're using. # Limit the major version to the major version of ElasticSearch we're using.

View File

@ -87,7 +87,16 @@ html(lang="en")
| {% block footer_scripts_pre %}{% endblock %} | {% block footer_scripts_pre %}{% endblock %}
| {% block footer_scripts %}{% endblock %} | {% block footer_scripts %}{% endblock %}
script.
// When sending an AJAX request, always add the X-CSRFToken header to it.
var csrf_token = "{{ csrf_token() }}";
$.ajaxSetup({
beforeSend: function (xhr, settings) {
if (!/^(GET|HEAD|OPTIONS|TRACE)$/i.test(settings.type) && !this.crossDomain) {
xhr.setRequestHeader("X-CSRFToken", csrf_token);
}
}
});
script. script.
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){ (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){