Tie up CSRF tokens in the frontend

This commit is contained in:
Antonin Delpeuch 2019-10-14 16:08:15 +01:00
parent 5dc005749a
commit 9ae6a7a581
11 changed files with 49 additions and 15 deletions

View File

@ -317,7 +317,7 @@ public abstract class Command {
w.close();
}
static protected void respondJSON(HttpServletResponse response, Object o)
public static void respondJSON(HttpServletResponse response, Object o)
throws IOException {
respondJSON(response, o, new Properties());

View File

@ -34,6 +34,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
package com.google.refine.commands;
import java.io.IOException;
import java.util.Collections;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
@ -67,7 +68,7 @@ public class SetPreferenceCommand extends Command {
ps.put(prefName, PreferenceStore.loadObject(o));
respond(response, "{ \"code\" : \"ok\" }");
respondJSON(response, Collections.singletonMap("code", "ok"));
} catch (IOException e) {
respondException(response, e);
}

View File

@ -34,7 +34,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
package com.google.refine.commands.importing;
import java.io.IOException;
import java.io.Writer;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
@ -46,7 +45,6 @@ import com.fasterxml.jackson.annotation.JsonProperty;
import com.google.refine.commands.Command;
import com.google.refine.importing.ImportingJob;
import com.google.refine.importing.ImportingManager;
import com.google.refine.util.ParsingUtilities;
public class GetImportingJobStatusCommand extends Command {
protected static class JobStatusResponse {
@ -77,11 +75,10 @@ public class GetImportingJobStatusCommand extends Command {
long jobID = Long.parseLong(request.getParameter("jobID"));
ImportingJob job = ImportingManager.getJob(jobID);
Writer w = response.getWriter();
if (job == null) {
ParsingUtilities.defaultWriter.writeValue(w, new JobStatusResponse("error", "No such import job", null));
respondJSON(response, new JobStatusResponse("error", "No such import job", null));
} else {
ParsingUtilities.defaultWriter.writeValue(w, new JobStatusResponse("ok", null, job));
respondJSON(response, new JobStatusResponse("ok", null, job));
}
}
}

View File

@ -63,6 +63,8 @@ public class ImportingControllerCommand extends Command {
ImportingController controller = getController(request);
if (controller != null) {
response.setCharacterEncoding("UTF-8");
response.setHeader("Content-Type", "application/json");
controller.doPost(request, response);
} else {
HttpUtilities.respond(response, "error", "No such import controller");
@ -75,6 +77,8 @@ public class ImportingControllerCommand extends Command {
ImportingController controller = getController(request);
if (controller != null) {
response.setCharacterEncoding("UTF-8");
response.setHeader("Content-Type", "application/json");
controller.doPost(request, response);
} else {
HttpUtilities.respond(response, "error", "No such import controller");

View File

@ -50,6 +50,7 @@ import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.google.refine.RefineServlet;
import com.google.refine.commands.Command;
import com.google.refine.commands.HttpUtilities;
import com.google.refine.importing.ImportingManager.Format;
import com.google.refine.util.JSONUtilities;
@ -218,7 +219,7 @@ public class DefaultImportingController implements ImportingController {
JSONUtilities.safePut(result, "status", "ok");
JSONUtilities.safePut(result, "options", options);
HttpUtilities.respond(response, result.toString());
Command.respondJSON(response, result);
} else {
HttpUtilities.respond(response, "error", "Unrecognized format or format has no parser");
}

View File

@ -251,7 +251,7 @@ Refine.DefaultImportingController.prototype.getPreviewData = function(callback,
var result = {};
$.post(
"command/core/get-models?" + $.param({ "importingJobID" : this._jobID }),
"command/core/get-models?" + $.param({ "importingJobID" : self._jobID }),
null,
function(data) {
for (var n in data) {

View File

@ -332,12 +332,12 @@ Refine.DefaultImportingController.prototype._commitFileSelection = function() {
$.post(
"command/core/importing-controller?" + $.param({
"controller": "core/default-importing-controller",
"jobID": this._jobID,
"jobID": self._jobID,
"subCommand": "update-file-selection",
"csrf_token": token
}),
{
"fileSelection" : JSON.stringify(this._job.config.fileSelection)
"fileSelection" : JSON.stringify(self._job.config.fileSelection)
},
function(data) {
dismissBusy();
@ -348,7 +348,7 @@ Refine.DefaultImportingController.prototype._commitFileSelection = function() {
self._createProjectUI.showImportJobError((data.message) ? ($.i18n('core-index-import/error')+ ' ' + data.message) : $.i18n('core-index-import/unknown-err'));
} else {
// Different files might be selected. We start over again.
delete this._parserOptions;
delete self._parserOptions;
self._job = data.job;
self._showParsingPanel(true);

View File

@ -35,7 +35,7 @@ Refine.ImportProjectUI = function(elmt) {
elmt.html(DOM.loadHTML("core", "scripts/index/import-project-ui.html"));
Refine.wrapCSRF(function(token) {
elem.attr('action', "command/core/import-project?" + $.param({ csrf_token: token});
elmt.attr('action', "command/core/import-project?" + $.param({ csrf_token: token}));
});
this._elmt = elmt;

View File

@ -33,6 +33,37 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
var preferenceUIs = [];
var Refine = {
};
// Requests a CSRF token and calls the supplied callback
// with the token
Refine.wrapCSRF = function(onCSRF) {
$.get(
"command/core/get-csrf-token",
{},
function(response) {
onCSRF(response['token']);
},
"json"
);
};
// Performs a POST request where an additional CSRF token
// is supplied in the POST data. The arguments match those
// of $.post().
Refine.postCSRF = function(url, data, success, dataType, failCallback) {
return Refine.wrapCSRF(function(token) {
var fullData = data || {};
fullData['csrf_token'] = token;
var req = $.post(url, fullData, success, dataType);
if (failCallback !== undefined) {
req.fail(failCallback);
}
});
};
var lang = (navigator.language|| navigator.userLanguage).split("-")[0];
var dictionary = "";
$.ajax({

View File

@ -190,7 +190,7 @@ ExporterManager.handlers.exportProject = function() {
var name = window.prompt(prompt, theProject.metadata.name);
if (name) {
var dismiss = DialogSystem.showBusy($.i18n('gdata-exporter/uploading'));
$.post(
Refine.postCSRF(
"command/gdata/upload",
{
"project" : theProject.id,

View File

@ -200,7 +200,7 @@ ProcessPanel.prototype._render = function(newData) {
} else {
if (window.confirm($.i18n('core-project/last-op-er')+':\n' + messages +
'\n\n'+$.i18n('core-project/continue-remaining')+'?')) {
$.post(
Refine.postCSRF(
"command/core/apply-operations?" + $.param({ project: theProject.id }),
{ operations: '[]' },
function(o) {},