背景
在一张图片增加相干文字,而后转化为 base64 数据,上传至服务器。当代码上线写完部署到测试环境,控制台报出如下错题:
Uncaught (in promise) DOMException: Failed to execute 'toDataURL' on 'HTMLCanvasElement': Tainted canvases may not be exported
通过排查,页面在申请图片时产生跨域状况,canvas 认为该图片数据为 净化的数据
,是不平安的数据,无奈导出 base64 数据。
为什么 canvas 认为跨域图片数据为 净化的数据
当申请跨域图片数据,而未满足跨域申请资源的条件时。如果 canvas 应用未经跨域容许的图片的原始数据,这些是不可信的数据,可能会裸露页面的数据。
申请图片资源 – 同域
Request Headers 带有 cookie。图片数据是被 canvas 信赖的。
申请图片资源 – 跨域
默认状况下,间接申请跨域图片。因为不合乎跨域申请资源的条件,图片数据是不被 canvas 信赖的。
为了解决图片跨域资源共享的问题,<img>
元素提供了反对的属性:crossOrigin
,该属性一共有两个值可选:anonymous
和 use-credentials
,上面列举了两者的应用场景,以及满足的条件。
anonymous | use-credentials | |
---|---|---|
用处 | 匿名申请跨域图片资源,不会发送证书(比方 cookie 等) | 具名申请跨域图片资源,会携带证书数据 |
Request Headers | origin | origin、cookie |
Response headers | Access-Control-Allow-Origin | Access-Control-Allow-Origin、Access-Control-Allow-Credentials |
所需条件 | Access-Control-Allow-Origin 字段值须要蕴含申请域。 | Access-Control-Allow-Origin 字段值须要蕴含申请域,且不能为通配符 *。Access-Control-Allow-Credentials 字段值须要为 true,表明容许申请发送证书数据。 |
代码示例:
// page origin is https://a.com
const canvas = document.createElement('canvas');
const context = canvas.getContext('2d');
const img = new Image();
img.crossOrigin = 'anonymous';
img.onload = () => {context.drawImage(this, 0, 0);
context.getImageData(0, 0, img.width, img.height);
};
img.src = 'https://b.com/a.png';
结束语
总结了申请图片资源的所有场景:同域、匿名跨域、具名跨域,以及跨域胜利所需的条件。心愿能够帮到遇到相似问题的小伙伴。
参考
- CORS_enabled_image
- HTMLImageElement.crossOrigin
- 跨源资源共享(CORS)
- 跨源相干机制综述(三):crossorigin 属性
- canvas-todataurl-securityerror