1.前言
在使用halo博客的适合,我碰到了一个困扰了我很久的小问题。最近在Halo博客上写作时,我发现文章中使用链接卡片时,封面图竟然无法加载出来,显示效果非常奇怪。尽管图片本身是可以加载的,但链接卡片却始终不显示封面图,感觉非常奇怪。经过一番调试,终于找到了问题所在。今天,我想和大家分享一下这个小问题的解决过程和一些心得,希望能帮到你们。
2.初步发现问题
当时,我在文章中添加了一个链接卡片,本来是想展示一张封面图的,但是奇怪的事情发生了,图片加载不出来,只能看到链接卡片的框架,却没有封面图显示。最初,我并没有察觉到哪里出了问题。毕竟图片和链接都是正常的,封面图也应该可以加载,为什么最终却看不到呢?

后来我发现,在浏览器中查看该链接卡片时,控制台并没有任何报错,意味着图片本身的路径是正确的,也没有涉及到其他问题。那么到底是什么原因呢?进一步排查后,我发现问题的关键在于浏览器的请求设置。
3.问题分析
通过一些调试工具,我发现,实际上问题并不出在图片本身。问题的根源在于链接卡片(<hyperlink-card>)的标签内部,它有一个属性referrerpolicy="no-referrer"。你也许会问,这个属性有什么问题?
referrerpolicy是一个控制浏览器发送请求时如何携带Referer头的属性。具体来说,当referrerpolicy="no-referrer"时,浏览器会完全禁止发送Referer头部,这就意味着当链接卡片加载图片时,浏览器不会将当前页面的地址(即Referer)传递给目标服务器。而在我的情况下,目标服务器对象存储COS。

为什么Referer头这么重要呢?COS的防盗链设置要求必须带有Referer信息,才能验证请求是否来自合法的页面。如果没有Referer,COS就会拒绝这个请求,导致图片无法加载。因此,问题的本质就是referrerpolicy="no-referrer"阻止了浏览器将Referer信息传递给COS,从而导致封面图无法显示。
4. 为什么不可以使用“空Referer”?
有些人可能会想,既然referrerpolicy="no-referrer"这么方便,为什么不直接使用呢?其实这存在一定的安全风险。虽然允许空Referer能解决图片加载的问题,但这种做法会降低安全性,尤其是在处理敏感数据或者涉及跨站请求的场景下。为了确保页面和图片加载的安全,最好还是采用其他的策略来解决问题,而不是一味地放宽安全控制。
5.解决方案
经过一番深入分析后,我决定不再继续纠结于为什么<hyperlink-card>标签默认会使用no-referrer。其实,解决问题的方法很简单,只需要修改referrerpolicy的值,就能让图片正常加载。


我将referrerpolicy="no-referrer"更改为referrerpolicy="strict-origin-when-cross-origin",这种设置在跨域请求时仅发送源信息作为Referer。简而言之,就是只发送域名部分,而不包括路径和查询字符串。这个设置既能够保证加载图片时传递Referer信息,又能保证一定的安全性。


代码如下,只需要把如下代码用forEach循环实现就行了。
document
.querySelectorAll('hyperlink-card')[0]
.shadowRoot
.querySelectorAll('img.usp-n3v8cb[referrerpolicy="no-referrer"]')[0]
.setAttribute('referrerpolicy', 'strict-origin-when-cross-origin')6.代码实现
这里是我在实际代码中应用的解决方案。通过以下代码,我可以修改每一个<hyperlink-card>标签下的图片,确保它们使用更安全的referrerpolicy设置。
// 解决链接卡片图片加载时不发送Referer头
document.addEventListener('DOMContentLoaded', function() {
setTimeout(() => {
const hyperlinks = document.querySelectorAll('hyperlink-card');
hyperlinks.forEach(link => {
if (!link.shadowRoot || link.shadowRoot.mode !== 'open') return;
const imgs = link.shadowRoot.querySelectorAll('img.usp-n3v8cb[referrerpolicy="no-referrer"]');
imgs.forEach(img => {
img.setAttribute('referrerpolicy', 'strict-origin-when-cross-origin');
});
});
}, 500);
});
上面的代码通过querySelectorAll查找所有<hyperlink-card>标签中的<img>元素,并修改其referrerpolicy属性为strict-origin-when-cross-origin。这个延迟对于大多数浏览器来说是足够的。
7.总结
今天的这个小问题其实是在开发过程中经常遇到的类型:看似小小的配置失误,可能就会导致我们在页面上看到奇怪的效果。而这个问题的解决,其实也并没有想象中的复杂。只需要理解referrerpolicy的作用和如何影响跨域请求,就能够找到解决办法。对于开发者来说,掌握这些小细节能够帮助我们快速定位和解决问题,提升开发效率。每当遇到类似的开发问题时,我也会感叹:解决问题的过程往往充满了挑战,但每一次都能从中学到一些新东西。希望今天的分享能对你们有所帮助,特别是那些也在使用链接卡片或者面临类似问题的朋友。如果你们有任何问题或者其他的开发经验,欢迎留言分享,我们一起探讨!
评论区