Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

获取微信头像的 base64 数据 #77

Open
ufologist opened this issue Feb 21, 2019 · 1 comment
Open

获取微信头像的 base64 数据 #77

ufologist opened this issue Feb 21, 2019 · 1 comment

Comments

@ufologist
Copy link
Member

应用场景

  • 前端生成一张图片, 一般是基于页面的内容(DOM)生成一张用于分享的海报形式的图片(例如通过 html2canvas)
  • 特殊在于分享的图片要包含微信用户的头像(图片位于 thirdwx.qlogo.cn 域名, 没有转存到自己的域名下)
  • 微信用户的头像图片相当于页面是跨域

原理

想要获取图片的 base64 数据, 我们大概都知道, 需要将图片绘制到 canvas 上, 再通过 toDataURL 方法拿到 DataURL 数据, 即 base64 的图片数据

结论与重点

  • 图片必须支持 CORS 跨域
  • 避免触发浏览器的缓存机制, 以免浏览器拿到的是缓存数据而没有携带 CORS 策略

示例

generate-wx-headimgurl-dom-image | gist

遇到的坑

  • 当加载图片时, 如果开启了 crossOrigin 机制, 服务器必须遵循 CORS 规范, 返回 Access-Control-Allow-Origin 头, 否则会被浏览器阻止(cancel)掉, 触发 onerror 回调
    • 由于微信头像默认加载时不会返回 CORS 规范, 只有在请求时开启 Origin 才会返回 CORS 规范的内容
    • 在 PC 端浏览器上如果不使用 Disable cache, 会加载图片失败, 触发 onerror 回调
    • 因此在移动端浏览器上测试会发现也是触发的 onerror 回调(因为我们在页面中先预览了一次微信用户的头像)
    • 如果需要解决这个问题, 可以在第一次加载微信用户头像的时候就开启 crossOrigin 机制(但不排除命中其他应用种下的缓存)
    • 例如: <img src="http://thirdwx.qlogo.cn/xx/132" crossorigin="anonymous">
    • 或者再次加载图片的时候带上随机参数, 避免浏览器缓存(这个方案更稳定靠谱)
    • cors-match-cache
  • 加载跨域的图片时必须让浏览器执行跨域请求(CORS)(开启 crossOrigin 机制), 否则将跨域的图片绘制到 canvas 上会导致 canvas 被污染, 执行 canvas.toDataURL 会因为安全风险而导致执行失败抛出异常
  • 开启 html2canvasuseCORS 选项, 理论上就是运用 CORS 机制跨域加载图片
    • 但受缓存的影响, 生成的图片会没有微信头像
    • 因此可以先自行获取到图片的 base64 数据, 替换掉图片的 src 避免产生跨域的问题
    • 如果开启 allowTaint 选项, 会导致生成图片失败

补充

关于在 HTTPS 的页面中加载 HTTP 的内容, 我们的印象中是所有的 HTTP 的内容都会被浏览器阻止

  • 但事实并不是这样的, 例如我们常见的 CSS/JS/XHR 都会被浏览器阻止, 浏览器会给出 ERROR 级别的错误
    • 注意: 早期的浏览器版本(我测试的 chrome 12 版本), 混合的 HTTP 内容都可以加载成功, 不会被浏览器屏蔽, 只是有警告
  • 但发现图片内容是可以加载成功的, 不会被浏览器阻止, 由此可以推断出媒体类无代码执行权限的内容(即纯用于显示的内容)是不会被浏览器阻止的, 只是给出 WARN 级别的警告信息

在开发的过程中需要生成带微信头像的图片, 在 PC 端(因为开发习惯了使用 Disable cache)测试都是可以的, 一到移动端就不行了, 试过很多办法后无果(〒_〒 绝望了...)
突发奇想将微信头像 URL 的 HTTPS 替换成 HTTP, 发现就能够获取到 base64 的数据了, 很是诡异.
现在理清楚背后的故事, 原来是缓存在作怪, 只要不触发浏览器的缓存就能够通过 CORS 跨域机制获取到图片的 base64 的数据

参考

@Mark24Code
Copy link

感谢笔记

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants