记录一次因为图片问题而导致微信支付报错的事故

703 阅读3分钟

原因以及防盗链

原因:在h5项目中访问第三方api返回的图片链接返回403错误,但是把该url输入浏览器的搜索栏中却可以成功访问。百度一番之后,了解到是第三方的图片链接做了防盗链处理。

防盗链:防盗链的规则一般是先判断请求中的referer信息,如果referer的请求源不在自己白名单内,就返回403或者相应的处理(重定向到别的图片等等)。在nginx中常用的配置如下:

location ~* \.(gif|jpg|jpeg|png|bmp|swf|flv)$ {
    valid_referers none blocked 域名/IP;
     if ($invalid_referer) {
         rewrite ^/ https://xxxxx/404.png;
         # return 403;
    }
}

解决办法

有问题肯定要解决的,所以我又又百度了一番后成功的找到了解决办法。

方法一:

只需要在html的head中添加以下代码:

<meta name="referrer" content="no-referrer" />

这里贴下MDN中Referrer-Policy的几种值

标题含义
no-referrer整个 Referer 首部会被移除。访问来源信息不随着请求一起发送。
no-referrer-when-downgrade在同等安全级别的情况下,引用页面的地址会被发送(HTTPS->HTTPS),但是在降级的情况下不会被发送 (HTTPS->HTTP)。
origin在任何情况下,仅发送文件的源作为引用地址。例如 example.com/page.html 会将 example.com/ 作为引用地址。
origin-when-cross-origin对于同源的请求,会发送完整的URL作为引用地址,但是对于非同源请求仅发送文件的源。
same-origin对于同源的请求会发送引用地址,但是对于非同源请求则不发送引用地址信息。
strict-origin在同等安全级别的情况下,发送文件的源作为引用地址(HTTPS->HTTPS),但是在降级的情况下不会发送 (HTTPS->HTTP)。
strict-origin-when-cross-origin对于同源的请求,会发送完整的URL作为引用地址;在同等安全级别的情况下,发送文件的源作为引用地址(HTTPS->HTTPS);在降级的情况下不发送此首部 (HTTPS->HTTP)。
unsafe-url无论是同源请求还是非同源请求,都发送完整的 URL(移除参数信息之后)作为引用地址。

更详细的文档:Referrer-Policy

设置以上代码后就可以成功访问到图片链接啦(嘿嘿,真简单)。

就在我以为问题完美解决的时候,项目中的微信支付出现了“商家参数有误,请联系商家解决”,通过微信支付文档可以知道,是因为调起h5支付的referer为空导致的,如图:

image.png

所以不能通过全局meta来访问防盗链图片,我们可以设置单个标签的referrer来实现:

<img referrer="no-referrer|origin|unsafe-url" src="{{src}}"/>

需要注意的是,这个方法不支持gif图片,只能显示静态图片。

方法二:

代理图片,使用images.weserv.nl方案,这样就可以优雅的访问图片啦。

getImage(url){
	// 把现在的图片连接传进来,返回一个不受限制的路径
	if(url !== undefined){
		return url.replace(/^(http)[s]*(\:\/\/)/,'https://images.weserv.nl/?url=');
	}
}

Images.weserv.nl,是一个利用cloudflare的CDN,可缓存、直链Google、Drive、OneDrive等图片的网站,同时,发布了这样的源码,自己能够创立,用于图片存储等。支持IPv6。

image.weserv.nl的文档

image.weserv.nl的开源地址

结语

大家端午快乐!