[ADD] client-side CSRF support

* add CSRF token as core.csrf_token
* add CSRF tokens to client-generated and/or JS-submitted forms
* remove broken "compatibility" mode of web.ajax.post

  /cc @dmo-odoo I've no idea how that was supposed to work, from looking
  things up all modern browsers seem to support FormData, and old IEs
  which don't don't support fallbacks either and would require
  submitting an actual form as fallback so...
This commit is contained in:
Xavier Morel
2015-10-01 01:36:50 +02:00
committed by Olivier Dony
parent 7753ed7ce4
commit cea29e0c01
7 changed files with 40 additions and 15 deletions
@@ -2,6 +2,7 @@
<t t-name="ImportView">
<t t-set="_id" t-value="_.uniqueId('export')"/>
<form action="" method="post" enctype="multipart/form-data" class="oe_import">
<input type="hidden" name="csrf_token" t-att-value="csrf_token"/>
<input type="hidden" name="session_id"
t-att-value="widget.session.session_id"/>
<input type="hidden" name="import_id"/>
+10 -7
View File
@@ -1,6 +1,7 @@
odoo.define('web.ajax', function (require) {
"use strict";
var core = require('web.core');
var time = require('web.time');
var utils = require('web.utils');
@@ -238,6 +239,11 @@ function get_file(options) {
method: 'POST'
}).appendTo(document.body);
}
if (core.csrf_token) {
$('<input type="hidden" name="csrf_token">')
.val(core.csrf_token)
.appendTo($form_data);
}
var hparams = _.extend({}, options.data || {}, {token: token});
_.each(hparams, function (value, key) {
@@ -292,19 +298,16 @@ function post (controller_url, data) {
};
var Def = $.Deferred();
var compatibility = !(typeof(FormData));
var postData = compatibility ? new FormDataCompatibility() : new FormData();
var postData = new FormData();
$.each(data, function(i,val) {
postData.append(i, val);
});
var xhr = new XMLHttpRequest();
if(compatibility) {
postData.setContentTypeHeader(xhr);
postData = postData.buildBody();
if (core.csrf_token) {
postData.append('csrf_token', core.csrf_token);
}
var xhr = new XMLHttpRequest();
if(xhr.upload) xhr.upload.addEventListener('progress', progressHandler(Def), false);
var ajaxDef = $.ajax(controller_url, {
+2 -1
View File
@@ -988,7 +988,8 @@
<t t-name="HiddenInputFile">
<div t-attf-class="oe_hidden_input_file #{fileupload_class or ''}" t-att-style="fileupload_style">
<form class="o_form_binary_form" t-att-target="fileupload_id"
method="post" enctype="multipart/form-data" t-att-action="fileupload_action || '/web/binary/upload'">
method="post" enctype="multipart/form-data" t-att-action="fileupload_action || '/web/binary/upload'">
<input type="hidden" name="csrf_token" t-att-value="csrf_token"/>
<input type="hidden" name="session_id" value="" t-if="widget.session.override_session"/>
<input type="hidden" name="callback" t-att-value="fileupload_id"/>
<t t-raw="0"/>
+7
View File
@@ -301,6 +301,13 @@
<t t-call="web.layout">
<t t-set="head">
<t t-call-assets="web.assets_common"/>
<script type="text/javascript">
odoo.define('web.csrf', function (require) {
var token = "<t t-esc="request.csrf_token(None)"/>";
require('web.core').csrf_token = token;
require('qweb').default_dict.csrf_token = token;
});
</script>
<t t-call-assets="web.assets_backend"/>
&lt;!--[if lte IE 9]&gt; <link rel="stylesheet" href="/web/static/src/css/ie.css"/> &lt;![endif]--&gt;
<script type="text/javascript">
+1 -2
View File
@@ -88,8 +88,7 @@
enctype="multipart/form-data"
target="fileframe"
class="form-inline">
<!-- why is this template rendered client side? -->
<!-- input type="hidden" name="csrf_token" t-att-value="request.csrf_token()"/-->
<input type="hidden" name="csrf_token" t-att-value="csrf_token"/>
<div class="well">
<div class="form-group pull-left">
<input type="file" name="upload" t-att-accept="widget.accept" multiple="multiple" style="position: absolute; opacity: 0; width: 1px; height: 1px;"/>
+12 -5
View File
@@ -142,16 +142,23 @@ var error = function(data, url) {
$error.modal('show');
};
function _add_input(form, name, value) {
var param = document.createElement('input');
param.setAttribute('type', 'hidden');
param.setAttribute('name', name);
param.setAttribute('value', value);
form.appendChild(param);
}
var form = function (url, method, params) {
var form = document.createElement('form');
form.setAttribute('action', url);
form.setAttribute('method', method);
if (core.csrf_token) {
_add_input(form, 'csrf_token', core.csrf_token);
}
_.each(params, function (v, k) {
var param = document.createElement('input');
param.setAttribute('type', 'hidden');
param.setAttribute('name', k);
param.setAttribute('value', v);
form.appendChild(param);
_add_input(form, k, v);
});
document.body.appendChild(form);
form.submit();
@@ -130,6 +130,13 @@
<t t-call-assets="website.assets_frontend" t-js="false"/>
<t t-call-assets="web.assets_common" t-css="false"/>
<t t-call-assets="website.assets_frontend" t-css="false"/>
<script type="text/javascript">
odoo.define('web.csrf', function (require) {
var token = "<t t-esc="request.csrf_token(None)"/>";
require('web.core').csrf_token = token;
require('qweb').default_dict.csrf_token = token;
});
</script>
<t t-raw="head or ''" name='layout_head'/>
</head>