javascript – 为什么使用HTMLObjectElement动态生成SVG会导致跨源错误?
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了javascript – 为什么使用HTMLObjectElement动态生成SVG会导致跨源错误?,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含3170字,纯文字阅读大概需要5分钟。
内容图文
![javascript – 为什么使用HTMLObjectElement动态生成SVG会导致跨源错误?](/upload/InfoBanner/zyjiaocheng/698/0d0e914bb082484fa7c22e85959453a3.jpg)
请考虑以下JavaScript代码段:
const app = document.getElementById('root');
const svg = `<svg version="1.1" id="Layer_1"...`;
const obj = document.createElement('object');
obj.setAttribute('type', 'image/svg+xml');
obj.setAttribute('data', `data:image/svg+xml; base64,${btoa(svg)}`);
app.appendChild(obj);
setTimeout(() => {
console.log(obj.contentDocument.querySelector('svg'));
}, 1500);
(有关完整示例,请参阅this JSFiddle)
运行时,控制台(Google Chrome)中会出现以下错误:
Uncaught DOMException: Failed to read the ‘contentDocument’ property from ‘HTMLObjectElement’: Blocked a frame with origin “07001” from accessing a cross-origin frame.
at setTimeout (07002)
考虑到这一点;
>为什么在尝试访问完全动态创建的对象的contentDocument而没有外部资源时,这被视为跨源请求?
>有没有办法以这种方式动态生成SVG,而不会冒犯浏览器的跨源策略?
解决方法:
这里的问题是data: URLs are treated as having a unique origin与创建嵌入数据的上下文的起源不同:context:
Note: Data URLs are treated as unique opaque origins by modern browsers, rather than inheriting the origin of the settings object responsible for the navigation.
WHATWG规范描述了how content documents are accessed,其中包括交叉原点检查. WHATWG same-origin comparison永远不会将传统的scheme-host-port“元组”原点视为等于“不透明”数据:origin.
相反,使用带有URL.createObjectURL的Blob来生成同源的临时URL,其内容将可由外部环境读取:
var svgUrl = URL.createObjectURL(new Blob([svg], {'type':'image/svg+xml'}));
obj.setAttribute('data', svgUrl);
我不知道原始数据:URL不允许这种方法的安全性原因,但它看起来确实有效. (我想因为生成的URL只能由生成它的原点读取,而数据:URL不知道如何只能通过其原始上下文的原始读取.)
另请注意,某些版本的Internet Explorer支持createObjectURL,但错误地将生成的URL视为具有空原点,这会导致此方法失败.
其他选择是:
>不要使用数据:URL,而是从与创建< object>的页面相同的源提供SVG内容.元件.
>抛弃< object>和contentDocument一起使用inline <svg> element代替(fiddle):
const obj = document.createElement('div');
obj.innerHTML = svg;
app.appendChild(obj);
setTimeout(() => {
console.log(obj.querySelector('svg'));
}, 1500);
大多数浏览器都支持内联< svg>元素(特别是IE 9.0;其他浏览器更早).这意味着你可以做到
<div>
<svg>
...
</svg>
</div>
它只会在< div>内呈现SVG文档正如你所料.
>根据您对SVG的要求,您可以在load it into a DOMParser中进行DOM探索/操作,并在解析器中进行.
var oParser = new DOMParser();
var svgDOM = oParser.parseFromString(svg, "text/xml");
console.log(svgDOM.documentElement.querySelector('path'));
svgDOM.documentElement.querySelector('path').remove();
但DOM模型将与< object>中呈现的SVG分开.要更改< object>,您需要序列化已解析的DOM结构并将其重新推送到data属性:
var oSerializer = new XMLSerializer();
var sXML = oSerializer.serializeToString(svgDOM);
obj.setAttribute('data', `data:image/svg+xml; base64,${btoa(sXML)}`);
这似乎不是超级高效的,因为它需要浏览器重新解析一个全新的SVG文档,但它将绕过安全限制.
想想< object>作为单向黑洞,可以接收SVG信息进行渲染,但不会暴露任何信息.但是,这不是一个信息问题,因为您拥有刚刚输入< object>的信息:contentDocument没有任何信息可以告诉您您还不知道.
但是,如果您想通过将侦听器附加到主页上执行代码的SVG结构中的组件来在SVG交互中创建组件,我认为这种方法不起作用. < object>之间的分离它的周围页面与< iframe>具有相同的嵌入关系.
内容总结
以上是互联网集市为您收集整理的javascript – 为什么使用HTMLObjectElement动态生成SVG会导致跨源错误?全部内容,希望文章能够帮你解决javascript – 为什么使用HTMLObjectElement动态生成SVG会导致跨源错误?所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。