NEWS

技术文章

canvas 导出图片的跨域安全

编辑:
阳程网络
发布时间:
2021-9-27
点击:
canvas 在绘制内容的时候,会创建一块画布,这块画布是干净的,此时,你可以往上面画文字、画图片、还可以画视频等。在绘制图片的时候,图片可能会来源于其它域名,比如:

在网页 https://www.zyv1999.com/index.html 
中创建一个 canvas 元素,在 canvas 上绘制一张图片,图片地址为 
https://image/suyan.png(不支持跨域),一旦把图片绘制到 canvas 上,当你使用 canvas.toDataURL() 时会报一个安全问题:




其实调用getImageData(),toBlob() 这些 api 也会报错。

关于这个问题,MDN 上也有描述:

The canvas's bitmap is not origin clean; at least some of its contents have or may have been loaded from a site other than the one from which the document itself was loaded.

解决这个问题核心思路是解决图片的跨域问题。

这里提个疑问,浏览器为啥要加入这个安全举措?可以把任何图片绘制到 canvas 上,但却不让把 canvas 导出?

在访问图片的时候,可以通过 crossorigin 来设置跨域访问图片,代码如下:

let image = new Image();
image.crossOrigin = 'anonymous';
image.addEventListener('load', () => {
    // image load success
});
image.addEventListener('error', () => {
   // image load error
});
image.src = src;
一旦设置 crossorigin 这个属性时,那么你的图片服务器必须支持跨域访问,否则将会报错:





解决这个问题让服务端支持跨域即可,如果服务端支持不了,可以通过 node 层写个代理:

const axios = require('axios');
const cors = require('cors');
const app = express();
// express 使用跨域插件
app.use(cors());

// 访问的图片域名,访问时添加参数 requrl,图片真正的地址
app.use('/img/content', (req, res) => {
    let url = req.query.requrl;
    axios.get(url, {
        responseType: 'arraybuffer'
    }).then(data => {
        res.set('Content-Type', 'image/jpeg');
        let content = Buffer.from(data.data, 'binary');
        res.end(content);
    });
});
其实不仅是图片,如果你在 canvas 中使用视频也会遇到这个问题。

总之,问题的核心是,你可以把任意网站的图片应用到你的网站,但是如果想使用图片中的数据,必须声明图片通过跨域访问,也就是说你用图片数据的时候,要和服务器打声招呼:'我要用你图片,帮忙加个白名单吧'。解决此类问题,归根结底是解决跨域问题。
标签  前端开发
下一条新闻: 利用Canvas人物动画
相关文章

Copyright@宁波阳程网络科技有限公司. All rights reserved. Powered by 阳程网络       备案号:浙ICP备 16017710号