HEXO 开发笔记(7)自建主题:安全与SEO
创建于 2026-06-19
更新于 2026-06-19
科技
hexo
主题开发
安全
SEO
4430 字 · 约 15 分钟

前言

本篇聚焦 DoraTiger 主题的安全功能和 SEO 优化。安全方面涵盖文章加密(AES-256-GCM)和外链重定向拦截;SEO 方面涵盖原生 Sitemap/Robots.txt 生成器和 JSON-LD 结构化数据。这些功能最早都是通过第三方插件实现的,在主题重构时选择集成到内部,主要是为了更好的适配性。

一、文章加密

1.1 为什么需要加密

加密功能最初也是用的第三方插件(hexo-blog-encrypt),重构时一体化集成到主题内部。原因是加密功能和文章渲染管线耦合很深 — 加密后的文章需要特殊的渲染流程(先解密再渲染),第三方插件的实现和主题的渲染管线配合起来有各种边界问题。

目前只加密了一篇文章 — 本科同学录。属于私密内容,不适合公开。

1.2 加密方案

采用构建时加密 + 运行时解密的方案,无需后端服务:

text
1
2
3
4
5
6
构建时(Node.js 服务端): 明文内容 → PBKDF2 密钥派生(100K 迭代)→ AES-256-GCM 加密 → 加密数据 + Salt + IV + Auth Tag 嵌入 HTML data 属性 运行时(浏览器 Web Crypto API): 用户输入密码 → PBKDF2 派生相同密钥 → AES-GCM 解密 → 显示内容

1.3 构建端加密

javascript
1
2
3
4
5
6
7
8
9
10
// scripts/filters/lib/encrypt.js function encryptContent(content, password) { const salt = crypto.randomBytes(16); // 16 字节随机盐值 const iv = crypto.randomBytes(12); // 12 字节随机 IV const key = crypto.pbkdf2Sync( // PBKDF2 派生密钥 password, salt, 100000, 32, "sha256" // 100K 迭代,SHA-256 ); const cipher = crypto.createCipheriv("aes-256-gcm", key, iv); // ... 加密 + 提取 auth tag }

1.4 运行时解密

javascript
1
2
3
4
5
6
7
8
9
10
11
// 内联在 footer.pug 中 async function decrypt(pwd) { var keyMat = await crypto.subtle.importKey('raw', ...); var key = await crypto.subtle.deriveKey({ name: 'PBKDF2', salt, iterations: 100000, hash: 'SHA-256' }, keyMat, ...); var pt = await crypto.subtle.decrypt({ name: 'AES-GCM', iv, tagLength: 128 }, key, combined); return new TextDecoder().decode(pt); }

1.5 使用方式

yaml
1
2
3
4
# front-matter password: "my-secret-password" abstract: "本文已加密,请输入密码查看" # 可选,覆盖默认提示 message: "请输入密码" # 可选,覆盖默认按钮文字

加密后对搜索引擎的影响:加密页面的内容对爬虫不可见,不会被收录。对于私密内容这正是期望的效果。

二、外链重定向拦截

2.1 从公安备案到外链安全

这个功能的由来有一个小故事。博客最初只做了 ICP 备案,后来接到公安电话通知需要做公安备案。备案完成后,自然就考虑到了外链安全性的问题 — 如果博客上的链接指向了恶意网站,作为站长是有责任的。

最早是利用 Yourls 短链服务做的外链跳转 — 每个外链先转成短链,用户点击时经过 Yourls 中间页。有一段时间 Hexo 的提交记录全是改链接的,把旧的直接链接替换成短链格式(顺便说一下,这也催生了那篇 服务器操作指北(6)Yourls 短链接服务部署)。

但后来觉得每次加外链都得去 Yourls 后台手动加一条记录,太麻烦了。就像图片之前用七牛云 CDN,最后也是嫌麻烦放弃了。所以参考知乎的外链跳转风格,构建了一个主题自用的方案 — 构建时自动识别外链,运行时通过中间页拦截。同时因为做了 网站公安备案小记,外链安全性也成了必须考虑的问题。

2.2 构建时注入

javascript
1
2
3
4
5
6
7
8
9
10
// scripts/filters/lib/redirect.js data.content = data.content.replace( /<a\s+([^>]*?)href=["']([^"']+)["']([^>]*)>/gi, (match, pre, url, post) => { if (!shouldRedirect(url)) return match; return `<a ... class="external-link" data-redirect="${encodeURIComponent(url)}" target="_blank" ...>`; } );

2.3 运行时拦截

pug
1
2
3
4
5
6
7
8
9
// layout/_include/_layout.pug script. document.addEventListener('click', (e) => { const link = e.target.closest('a[data-redirect]'); if (link) { e.preventDefault(); window.open('/redirect/?url=' + link.dataset.redirect); } });

2.4 配置

yaml
1
2
3
4
5
redirect: method: exclude # exclude(默认)| include exclude: - "superheaoz.top" # 自己的域名不拦截 - "github.com"

三、原生 Sitemap 与 SEO

3.1 从插件到内置

SitemapRobots.txt 最初也是用的第三方插件(hexo-generator-sitemap),重构时一体化集成。原因是这两个生成器逻辑不复杂,但和主题的配置体系(theme-config())结合后可以做到更精细的控制。

3.2 Sitemap 生成器

支持 XMLTXT 或两者同时输出,优先级和更新频率可通过配置调整:

javascript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// scripts/generators/lib/sitemap.js module.exports = function (locals) { const urls = []; urls.push({ loc: siteUrl + "/", freq: "daily", priority: 1.0 }); locals.posts.sort("-date").forEach(post => { urls.push({ loc: siteUrl + "/" + post.path, freq: changefreq, priority: 0.8, lastmod: post.updated }); }); if (format === "xml" || format === "both") results.push({ path: "sitemap.xml", data: buildXml(urls) }); if (format === "txt" || format === "both") results.push({ path: "sitemap.txt", data: buildTxt(urls) }); };

3.3 SEO 实际效果

这个博客主要还是以学习为目的,没有专门做 SEO 优化。简单对接了百度、谷歌、微软的站长统计功能 — 提交了 sitemap,配置了 robots.txt,加了 JSON-LD 结构化数据。对搜索引擎收录有一定帮助,但没有做过系统的 SEO 策略分析。

3.4 JSON-LD 结构化数据

pug
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// layout/_include/head.pug if(is_post()) script(type="application/ld+json"). { "@type": "Article", "headline": "#{page.title}", "author": { "@type": "Person", "name": "#{config.author}" }, "datePublished": "#{page.date}", "dateModified": "#{page.updated}" } else script(type="application/ld+json"). { "@type": "WebSite", "name": "#{config.title}", "url": "#{config.url}" }

四、总结

安全和 SEO 是博客主题容易忽略但非常重要的部分。加密功能保护私密内容,外链拦截降低安全风险(从公安备案到链接安全的完整链路),Sitemap 和结构化数据为搜索引擎提供基础支持。这些功能在 DoraTiger 中均为一体化集成,从第三方插件迁移到主题内部后,适配性和可控性都好了很多。

参考

本文作者: 有次元袋的 tiger
本文链接: https://www.superheaoz.top/2026/06/9008/
版权声明: 本站点所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 我的个人天地
手机扫码阅读