怎么解决canvas中获取跨域图片数据的问题?

简介: 怎么解决canvas中获取跨域图片数据的问题?

背景

在一张图片添加相关文字,然后转化为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

image.png

代码示例

// 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';

另外,跨域图片能正常裁剪(图片未转化成base64),应该满足三个条件:


img元素中设置crossorigin属性

图片允许跨域,设置响应头Access-Control-Allow-Origin

使用js方式请求图片资源, 需要避免使用缓存,设置url后加上时间戳,或者http头设置Cache-Control为no-cache

主要原因是:


如果使用跨域的资源画到canvas中,并且资源没有使用CORS去请求,canvas会被认为是被污染了, canvas可以正常展示,但是没办法使用toDataURL()或者toBlob()导出数据,见Allowing cross-origin use of images and canvas。 所以通过在img标签上设置crossorigin,启用CORS,属性值为anonymous,在CORS请求时不会发送认证信息,见HTML attribute: crossorigin。

在启用CORS请求跨域资源时,资源必须允许跨域,才能正常返回,最简单的方式设置响应头Access-Control-Allow-Origin

图片已经通过img标签加载过,浏览器默认会缓存下来,下次使用js方式再去请求,直接返回缓存的图片,如果缓存中的图片不是通过CORS 请求或者响应头中不存在Access-Control-Allow-Origin,都会导致报错

相关文章
|
Java 开发工具 Maven
springboot项目打包为sdk供其他项目引用
springboot项目打包为sdk供其他项目引用
1987 1
|
编解码 JavaScript 前端开发
jsQR 一个完全独立的javascript 二维码识别库
jsQR 是一款纯粹的由javascript实现的二维码识别库,可以在浏览器端使用,也可以在后端node.js环境使用。我之前使用过其他的识别库,例如:qrcode-reader 或其他,在使用上都比较麻烦,而且识别率并不高。jsQR是后来发现的,感觉(没有实际对比验证)jsQR识别率要更高些,使用起来也更简单,不需要安装其他依赖软件。
jsQR 一个完全独立的javascript 二维码识别库
|
关系型数据库 MySQL 数据库
MySQL开启远程访问权限
默认情况下,mysql只允许本地登录,但是多数情况下,我们需要访问服务器上的数据库资源,此时就需要开放MySQL的远程访问权限。 本文主要讲解如何开启MySQL的远程访问权限。
37365 7
MySQL开启远程访问权限
|
缓存 对象存储 数据安全/隐私保护
阿里云OSS图片访问出现跨域:Access to image at from origin has been blocked by CORS policy
阿里云OSS图片访问出现跨域:Access to image at from origin has been blocked by CORS policy
3717 0
阿里云OSS图片访问出现跨域:Access to image at from origin has been blocked by CORS policy
|
JavaScript 测试技术 API
跟随通义灵码一步步升级vue2(js)项目到vue3版本
Vue 3 相较于 Vue 2 在性能、特性和开发体验上都有显著提升。本文介绍了如何利用通义灵码逐步将 Vue 2 项目升级到 Vue 3,包括备份项目、了解新特性、选择升级方式、升级依赖、迁移组件和全局 API、调整测试代码等步骤,并提供了注意事项和常见问题的解决方案。
1090 4
|
12月前
|
安全 数据建模 应用服务中间件
如何给IP地址添加SSL证书(https)
为IP地址配置SSL证书实现HTTPS访问,需拥有固定公网IP,选择支持IP证书的CA,完成账户注册、证书申请、所有权验证及证书安装。验证过程涉及在服务器上放置特定文件,确保可访问。安装后需测试连接,注意兼容性和安全性,定期维护证书。
|
缓存 JavaScript 前端开发
解决阿里oss远程图片html2canvas生成海报时跨域问题(附代码)
解决阿里oss远程图片html2canvas生成海报时跨域问题(附代码)
2280 0
解决阿里oss远程图片html2canvas生成海报时跨域问题(附代码)
基于element-plus实现vue3+ts后台管理系统的组件封装(只需传入配置对象,就可以渲染出一个页面(表单+表格))
基于element-plus实现vue3+ts后台管理系统的组件封装(只需传入配置对象,就可以渲染出一个页面(表单+表格))
|
应用服务中间件 网络安全 nginx
nginx配置去掉路径中的指定字符
【6月更文挑战第25天】nginx配置去掉路径中的指定字符
740 0
|
移动开发 JavaScript 小程序
从零开始使用 UniApp 构建跨平台移动应用
从零开始使用 UniApp 构建跨平台移动应用
416 0