# 引言

终于又重启博客了,平时开发折腾过程中遇到的一些问题,感觉不错的会发布到博客中。

但是有些文章如果存在隐私内容,或者不打算公开的话,就不能放在博客中了,但是一些文章挂在网页上又可以方便自己查看,于是折腾了下 Hexo 的文章加密

# 调研

以前用 wordpress 的时候,也折腾过类似的需求,由于是 动态网站,所以其实还是比较方便的,这一次使用了
Hexo 这个 静态博客 框架,说实话我都怀疑有没有可行的方案🤣🤣🤣

不过好在还是找到了一个 Hexo 插件 hexo-blog-encrypt 能够实现文章加密的需求

# 插件安装

使用如下命令安装

npm install hexo-blog-encrypt --save

该插件的使用也很方便,使用时只需要在文章的 Front-matter 添加 password 即可。

---
title: Hello World
date: 2022-05-13 21:18:02
password: 12345
---

下面展开讲一些比较实用的设置,更详细的可以查看官方文档。 D0n9X1n/hexo-blog-encrypt: Yet, just another hexo plugin for security.

# 全局加密配置

分别为每篇文章设置密码,虽然很灵活,但是配置或者修改起来非常麻烦。

好在,我们可以针对 tag 做全局统一配置,这样需要进行加密的文章,只需要引入指定的 tag 分类即可

  1. Hexo 主配置文件 _config.yml 中新增全局配置
# Security - hexo-blog-encrypt
encrypt:
  silent: true
  theme: xray
  abstract: 这是一篇加密文章,需要密码才能继续阅读。
  message: 当前文章暂不对外可见,请输入密码后查看!
  tags:
    - {name: private, password: hello}
  wrong_pass_message: 抱歉,您输入的密码错误,请检查后重新输入。

其中的 tag 部分可以定义多个,不同加密系列,采取不同的密码

  1. 文章头部 Front-matter 引入加密的 tag
---
title: Password Test
date: 2022-05-03 21:28:03
tags:
    - private
---

这样文章就被加密了,密码就是 private 标签对应的密码

  1. 全局加密豁免

可能有这样的情况,属于 private 标签下的某篇文章可能需要公开,不可能说把密码直接在描述信息中公开吧。

好在插件配置 优先级文章Front-matter > _config.yml配置 > 默认配置

这时候,可以在 Front-matter 中对加密设置进行覆盖,只需要在使用 加密tag 的前提下,结合 password 来实现即可。在博客文章的头部添加 password 并设置为 "" 就能取消当前文章的加密

---
title: Password Test
date: 2022-05-03 21:28:03
tags:
    - private
password: ""
---
  1. 全局加密设置非全局密码

可能有如下场景,属于 private 标签下的某篇文章想要设置成不一样的密码。

还是利用配置的优先级在 Front-matter 中对加密设置进行覆盖即可,在博客文章的头部添加 password 并设置为 自定义密码 就可以使用 自定义密码 加密当前文章了


---
title: Password Test
date: 2022-05-03 21:28:03
tags:
    - private
password: "special"
---

# Shoka 主题适配

# 解密后目录不显示

为文章设置了 加密 后查看 之后,不经意间发现这些文章的目录在解密后却不显示了。

在插件的 github issues 中有相关问题的讨论 解密后目录不会更新・Issue #16

主要原因就是加密的时候, post.content 会变成加密后的串,所以原来的 TOC 生成逻辑就会针对加密后的内容。
所以这边我只能把原来的内容存进 post.origin 字段。

Shoka 主题的针对修改如下:

  1. 主题文件 themes/shoka/layout/_macro/sidebar.njk 找到 [宏]{.blue} render ,修改目录生成部分如下
<div class="inner">
     <!--modify begin-->
    {%- if display_toc %}
        {%- if (page.encrypt) %}
            {%- set toc = toc(page.origin) %}
        {%- else %}
            {%- set toc = toc(page.content) %}
        {%- endif %}
        {%- set display_toc = toc.length > 1 and display_toc %}
        {%- set related = _category_posts(page) %}
    {%- endif %}
     <!--modify end-->
    <!--others-->
</div>
  1. 还是主题文件 themes/shoka/layout/_macro/sidebar.njk

替换 <div class="panels">...</div> 如下

<div class="panels">
    <div class="inner">
        <div class="contents panel pjax" data-title="{{ __('sidebar.toc') }}">
            {%- if (page.encrypt) %}
                <div id="toc-div" style="display:none">
                    {%- if display_toc %}
                        {{ toc }}
                    {%- endif %}
                </div>
            {%- else %}
                {%- if display_toc %}
                    {{ toc }}
                {%- endif %}
            {%- endif %}
        </div>
        <div class="related panel pjax" data-title="{{ __('sidebar.related') }}">
            {%- if related %}
                <ul>
                    {{ related }}
                </ul>
            {%- endif %}
        </div>
        <div class="overview panel" data-title="{{ __('sidebar.overview') }}">
            {{ partial('_partials/sidebar/overview.njk', {}, {cache: true}) }}
        </div>
    </div>
</div>

主要缘由是现在加密后的文章未解密之前也可以看到 文章目录,虽然该目录不可点击,但是这很不 优雅

理想中的效果应该是:

  • 当文章加密后,访客只能看到侧边栏中的 站点概览 部分,不需要看到 文章目录 部分。
  • 当文章解密后,访客则可以看到 站点概览文章目录 两部分。

查看了 hexo-blog-encrypt 相关的 issues Archer 主题解密后 TOC 依旧不显示(已按手册修改)・Issue #67, 最总找到了一种 折中 的解决方法

这种方法并不是完全的加密,而是采用 障眼法 的方式,通过查看 html 源文件还是可以看到目录内容的,只是不显示罢了。

对于这个问题, hexo-blog-encrypt 插件的作者也作了说明: next 主题内没有 article.ejs 文件【TOC 相关】・Issue #162・D0n9X1n/hexo-blog-encrypt,暂时只能妥协。

前后效果对比如下,解锁前隐藏目录,解锁后再显示目录,但是目录区域一直存在

# 文章元数据显示加密图标

  1. 主题语言包 themes/shoka/languages/zh-CN.ymlpost 新增加密显示文字
post:
    encrypt: 『加密』

下一步骤引用的 post.encrypt 就是这里的配置

  1. 主题文件 themes/shoka/layout/_macro/postmeta.njk , 找到 [宏]{.blue} render 在  { %- set create_title = __('post.created') + __('symbol.colon') + full_date(item.date) }  上修改代码如下
{% macro render(item, full = false) %}
    <div class="meta">
        <!--modify begin-->
        {%- if item.encrypt %}
            <span class="item" title="{{ __('post.encrypt') }}" style="margin-right: -0.625rem">
                <span class="icon">
                    <i class="ic i-compress"></i>
                </span>
                <span class="encrypt">
                    <font>{{ __('post.encrypt') }}</font>
                </span>
            </span>
        {%- endif %}
        <!--modify end-->
        {%- set create_title = __('post.created') + __('symbol.colon') + full_date(item.date) %}
        <!--others-->
    </div>
{% endmacro %}
  1. 主题样式 themes/shoka/source/css/_common/components/post/post.styl 新增样式
span.encrypt {
    white-space: pre;
    the-transition();
    font {
        color: #d96e80
    }
    span {
        white-space: normal;
    }
    a {
        color: var(--primary-color);
    }
    margin-left: -0.415rem
}

最终效果如下,同样的效果在首页文章的预览标签也会出现~

hexo-encrypt-postmeta

# 结语

Hexo 三连完结撒花~~

更新于 阅读次数