XHR 从具有 CSP 保护的 iframe 中保存文档
XHR save document from within iframe with CSP protection
设置
我们是 运行 另一个(spring 引导)项目的 iframe 内的 spring 引导项目。
顶层项目包含一个集成视图,并控制在 iframe 中显示的程序。到目前为止一切顺利。
顶层有CSP保护,所以我们在iframe中能显示的只有可信资源,它们是:
"default-src 'self';" +
"style-src 'self';" +
"child-src 'self' " + getAllowedHosts() + " " + getDomain() + ";" +
"frame-src 'self' " + getAllowedHosts() + " " + getDomain() + ";" +
"img-src 'self' www.google-analytics.com;" +
"connect-src 'self' www.google-analytics.com " + getAllowedHosts() + ";" +
"font-src 'self';" +
"script-src 'self' www.googletagmanager.com www.google-analytics.com;";
iframe 中的项目包含以下 CSP 设置:
"default-src 'self';" +
"style-src 'self';" +
"child-src 'self';" +
"frame-src 'self';" +
"img-src 'self' www.google-analytics.com;" +
"connect-src 'self' www.google-analytics.com;" +
"font-src 'self';" +
"object-src 'self' blob:;" +
"script-src 'self' www.googletagmanager.com www.google-analytics.com;";
问题。
我正在尝试使用以下 javascript 代码下载生成的文件(一个 excel 文件,尽管类型无关紧要):
/**
* @param url the url to post to
* @param data formatted JSON string.
*/
function download(url, data) {
var xhr = new XMLHttpRequest();
xhr.open('POST', url, true);
xhr.responseType = 'blob';
xhr.onload = function () {
if (this.status === 200) {
var disposition = xhr.getResponseHeader('Content-Disposition');
var matches = /"([^"]*)"/.exec(disposition);
var filename = (matches != null && matches[1] ? matches[1] : 'REI.xlsx');
var type = xhr.getResponseHeader('Content-Type');
var blob = new Blob([this.response], {type: type});
if (typeof window.navigator.msSaveBlob !== 'undefined') {
// IE workaround for "HTML7007:
// One or more blob URLs were revoked by closing the blob for which they were created.
// These URLs will no longer resolve as the data backing the URL has been freed."
window.navigator.msSaveBlob(blob, filename);
return;
}
// use HTML5 a[download] attribute to specify filename
var a = document.createElement("a");
a.href = window.URL.createObjectURL(blob);
console.log(a.href);
a.download = filename;
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
}
};
xhr.setRequestHeader('Content-type', 'application/json');
xhr.send(data);
}
当我在 iframe 环境之外打开我的页面时,文件下载正常,但在 iframe 中我收到以下 CSP 错误:
Chrome:
Refused to frame '' because it violates the following Content Security Policy directive: "default-src *". Note that 'frame-src' was not explicitly set, so 'default-src' is used as a fallback.
Firefox:
Content Security Policy: The page’s settings blocked the loading of a resource at blob:https://localhost:8444/dd686147-ea7f-4711-86fd-715b4834e0ba (“default-src”).
最后我选择通过一个动态表单提交来完成,其中有一个输入字段,其中包含字符串化的 JSON 数据。
生成的下载函数:
/**
* @param url the url to post to
* @param data formatted JSON string.
*/
function download(url, data) {
var f = $('<form>')
.prop('method', 'post')
.prop('action', url)
.css('display', 'none')
.append($('<input type="text" name="data">').val(data));
$('body').append(f);
f.submit();
f.remove();
}
然而,这需要我在服务器端也更改 post,因此它接受 JSON 字符串而不是直接映射的 POJO。
设置
我们是 运行 另一个(spring 引导)项目的 iframe 内的 spring 引导项目。 顶层项目包含一个集成视图,并控制在 iframe 中显示的程序。到目前为止一切顺利。
顶层有CSP保护,所以我们在iframe中能显示的只有可信资源,它们是:
"default-src 'self';" +
"style-src 'self';" +
"child-src 'self' " + getAllowedHosts() + " " + getDomain() + ";" +
"frame-src 'self' " + getAllowedHosts() + " " + getDomain() + ";" +
"img-src 'self' www.google-analytics.com;" +
"connect-src 'self' www.google-analytics.com " + getAllowedHosts() + ";" +
"font-src 'self';" +
"script-src 'self' www.googletagmanager.com www.google-analytics.com;";
iframe 中的项目包含以下 CSP 设置:
"default-src 'self';" +
"style-src 'self';" +
"child-src 'self';" +
"frame-src 'self';" +
"img-src 'self' www.google-analytics.com;" +
"connect-src 'self' www.google-analytics.com;" +
"font-src 'self';" +
"object-src 'self' blob:;" +
"script-src 'self' www.googletagmanager.com www.google-analytics.com;";
问题。
我正在尝试使用以下 javascript 代码下载生成的文件(一个 excel 文件,尽管类型无关紧要):
/**
* @param url the url to post to
* @param data formatted JSON string.
*/
function download(url, data) {
var xhr = new XMLHttpRequest();
xhr.open('POST', url, true);
xhr.responseType = 'blob';
xhr.onload = function () {
if (this.status === 200) {
var disposition = xhr.getResponseHeader('Content-Disposition');
var matches = /"([^"]*)"/.exec(disposition);
var filename = (matches != null && matches[1] ? matches[1] : 'REI.xlsx');
var type = xhr.getResponseHeader('Content-Type');
var blob = new Blob([this.response], {type: type});
if (typeof window.navigator.msSaveBlob !== 'undefined') {
// IE workaround for "HTML7007:
// One or more blob URLs were revoked by closing the blob for which they were created.
// These URLs will no longer resolve as the data backing the URL has been freed."
window.navigator.msSaveBlob(blob, filename);
return;
}
// use HTML5 a[download] attribute to specify filename
var a = document.createElement("a");
a.href = window.URL.createObjectURL(blob);
console.log(a.href);
a.download = filename;
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
}
};
xhr.setRequestHeader('Content-type', 'application/json');
xhr.send(data);
}
当我在 iframe 环境之外打开我的页面时,文件下载正常,但在 iframe 中我收到以下 CSP 错误:
Chrome: Refused to frame '' because it violates the following Content Security Policy directive: "default-src *". Note that 'frame-src' was not explicitly set, so 'default-src' is used as a fallback. Firefox: Content Security Policy: The page’s settings blocked the loading of a resource at blob:https://localhost:8444/dd686147-ea7f-4711-86fd-715b4834e0ba (“default-src”).
最后我选择通过一个动态表单提交来完成,其中有一个输入字段,其中包含字符串化的 JSON 数据。
生成的下载函数:
/**
* @param url the url to post to
* @param data formatted JSON string.
*/
function download(url, data) {
var f = $('<form>')
.prop('method', 'post')
.prop('action', url)
.css('display', 'none')
.append($('<input type="text" name="data">').val(data));
$('body').append(f);
f.submit();
f.remove();
}
然而,这需要我在服务器端也更改 post,因此它接受 JSON 字符串而不是直接映射的 POJO。