这是一篇过期文章 [2024.07.22]

本篇文章已过期。

  • 本文作为临时过渡方案,已经完成了它的使命。
  • 虽然方案实现麻烦且不优雅,但目前仍可继续工作。
  • 更好的实现方案详见友链用户 @清羽飞扬 的文章:安全跳转页面·插件版

由于近期站长收到 wxb 的温暖来电😨,所以对博客安全额外关注。好巧不巧印象中在 友链朋友圈 刷到类似文章,于是立刻开展学习并全站自查。(当初刷到时还不以为然,没想到这么快就到我头上…)

本篇文章提供一个在 Hexo 实现的简单的方法,涉及到对插件源代码的修改(不优雅),但过渡时期可暂时容忍这一不足。我觉得整体思路是有参考性的。

插件安装与调整

安装插件的目的是,识别出所有的外部链接,并修改其 URL 的格式使之成为内部链接。URL 指向一个中间页(没错,就是我以前嗤之以鼻的「互联网壁垒」)。你可以选择其他方式完成这件事情(比如 Hugo 方案参考友链用户 @大大的蜗牛 的文章: Hugo 外部链接跳转提示页面

插件 hvnobug/hexo-external-link (github.com) 所做的就是这件事情。但是唯一缺点就是最终转换的链接不可定制,于是我就手动修改了一下源代码,即修改博客目录下 blogs\node_modules\hexo-filter-links\lib\filter.js 文件:

1
2
- NewhrefStr = 'href="' + config.url + '/go/#' + NewhrefStr + '"';
+ NewhrefStr = 'href="' + '/pages/go.html#' + NewhrefStr + '"';

这样链接就变成了我想要的样子:/pages/go.html#+ 编码为 Base64 的外部链接地址。

建立中间页

从上面转换后的中间连接可以知道,我设置的中间页位置为 /pages/go.html。其实我只是在 sourse/pages 目录下新建了 go.md 文件而已,Hexo 会自动渲染成 HTML。我这样做只是为了和某些页面统一而已。你也可以自己另外设计独立的页面。

go.md 基本内容如下(省略了样式代码,保留主要的 HTML,看思路即可):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
---
title:
date: 2024-02-22 00:00:00
aside: false
top_img:
---

<link rel="stylesheet" href="/css/simple_page.css">

<body>
<meta charset="utf-8"/>
<title>GO Page</title>
<div>
<p class="h3">您即将在 &nbsp; <span id="go_time">inf</span>s &nbsp;后跳转到以下地址</p>
<p class="to_address text_align">
</p>
<a href="" class="to_url button" style="color: #FFFFFF;">立即跳转</a>
</div>
</body>

<script>
// 链接解析与设置
const params = window.location.hash;
const encodedTarget = params.slice(1);
const target = atob(encodedTarget); // 对应插件的编解码方法

if (target) {
console.log('解析到的target',target,params,encodedTarget);
document.getElementsByClassName('to_url button')[0].href = target;
document.getElementsByClassName('to_address text_align')[0].textContent = '' + target; // 直接显示目标地址
} else {
console.error('外部链接跳转未指定重定向目标。');
}

// 倒计时逻辑
var second=5;
var time = document.getElementById("go_time");
function show() {

if(second==0){
//跳转页面
location.href=target;
}else{
second--; // 放在if的分支里可以避免出现负数的情况
}
//用来动态设置里面的内容
time.innerHTML=second+"";

}
//用来实现这个一秒实现一次这个方法
setInterval(show,1000);
</script>

不太建议全站启用外链中间页,只对文章内容启用中间页即可。

附一份白名单,涵盖程序员常用外链(云服务平台、博客网站、笔记网站等):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
exclude:  
- 'github.com'
- 'tencent.com'
- 'aliyun.com'
- 'csdn.net'
- 'juejin.cn'
- 'jianshu.com'
- 'cnblogs.com'
- 'zhihu.com'
- 'bilibili.com'
- 'gitee.com'
- 'feishu.cn'
- 'yuque.com'
- 'kdocs.cn'
# 对应子域名白名单
- "*.uuanqin.top" # 这条有必要。否则 www.uuanqin.top 会识别为外链
- '*.github.com'
- '*.tencent.com'
- '*.aliyun.com'
- '*.csdn.net'
- '*.juejin.cn'
- '*.jianshu.com'
- '*.cnblogs.com'
- '*.zhihu.com'
- '*.bilibili.com'
- '*.gitee.com'
- '*.feishu.cn'
- '*.yuque.com'
- '*.kdocs.cn'
# 如果你想让友链文章不受阻塞,可以在此继续添加

后记

如果平时不喜欢各大网站中间页可以考虑安装这个脚本:Open the F**king URL Right Now (greasyfork.org)。或者尝试安装这个插件(我没试过):Skip Redirect (google.com)

Open the F**king URL Right Now

很多时候,在网上读到一篇好文章,我们被作者思想的深度,逻辑论证的缜密,内容的旁征博引所折服,这时我们往往也想去作者给出的相关链接上看看是怎样的奇文给了作者启发,写出了这样一篇振聋发聩的好文,于是点击链接,但是很多时候会突然跳出来一行字,要用户手动复制该链接贴到地址栏访问才行,被网站这样一折腾,刚刚提起来的求知欲一下子烟消云散了。

一次两次也倒罢了,但最近此风甚长,还有愈演愈烈之势,好好的超链接变成了一个个的『超不链接』,其他网站为了留存用户,延长用户停留时间,不惜以暴制暴,进行恶性竞争,结果就是互联网的用户体验变成了各大公司利益的牺牲品,在夹缝中艰难地生存,昔日的信息高速公路上就这样被人为地挖了许多坑。

为了把互联网体验变回我们熟悉的样子,为了让超链接能痛快地把用户送到终点,就写了这样一个简单的脚本…

——OldPanda

安全跳转必要性

有朋友问,为何要增设这样一个看似多余的步骤?“直接浏览不更直接吗?何必增添一个看似拖沓的跳转环节?”还有人,将其误解为纯粹的技术冗余,误以为这是效仿某些平台所设置的“用户不便”之举…Hexo-SafeGo 插件的核心目的,并非直接进行安全检测,而是作为一种自我保护机制,默默守护着网站的声誉与访问者的信任。现在的插件并没有能力能够主动扫描并消除网络中的所有威胁,但却能有效避免自身网站因缺少必要的安全协议而被浏览器标记为“不安全”,这一小步跳跃,实则是维护网站形象与信誉的一大步。

此插件的实施,更像是一份无形的“免责声明”,它向访问者无声宣告:作为网站管理者,我已经采取措施确保连接的安全性,即便遭遇外部链接可能带来的不确定性,也已事先提醒,尽到了告知的责任。在这个信息错综复杂的时代,这样的透明度与责任感显得尤为重要。

—— @清羽飞扬

看完 @清羽飞扬这篇文章 后,我决定将本文设置为过期文章。

本文参考