按理说作为一款支持共享和开放的系统,隐藏页面内容本身并不符合MediaWiki的设计理念。当然凡事都有特例,总有人会将它作为CMS系统来用,或者出于一些特殊原因不想将某些内容对外公开。心百科也不例外。
接下来是我在实践中的一些思路和方法。

一、CSS+JS方法(前端)

这可能是我最容易想到的方法了。不管是条目内容还是使用模板,只需要将隐藏内容用<div>包围起来,然后设定一个class或者是id(比如<div id="anon-hidden " class="hidden-text">)。然后对匿名用户默认使用某个特定主题(比如我一般将Timeless用于默认),由于匿名用户是无法更改主题的,所以就可以在mediawiki:主题名.css(比如mediawiki:timeless.css)页面中加入CSS代码:

.anon-hide  { display: none; }
#hidden-text { display: none; }

这样一来,当匿名用户浏览页面时,内容即被隐藏起来。不过这也只能骗骗小白,因为从源代码中能够很清晰地显示被隐藏的内容。或者也可以通过在浏览器地址栏后加入&useskin=vector-2022手动切换主题,那么原本针对timeless的CSS就不再起作用了。
如果增加一些JS代码呢?我把这个问题交给了DeepSeek,它给出的答复是:

在 MediaWiki 中,纯前端(JS + CSS)无法完全隐藏内容,使其不在源代码中显示,因为 HTML 源码始终会发送到浏览器。但你可以通过 动态加载 + 权限检查 的方式,对匿名用户隐藏内容,并减少直接暴露在 HTML 中的风险。

因为如果明文传输后通过简单的JS代码来隐藏,那么通过禁用JS就可能破解了限制。而动态加载的话要么直接将隐藏内容写入JS代码中(显然不符合我的要求),要么就是通过一个专门的页面或模板来加载内容。如果每个页面都有要隐藏的内容,内容各不相同并且字数还很多,那么充当中间存储的页面势必会越来越庞大,影响加载的效率。再者,该方法仍有一定的破解风险,只是难度稍大些。

二、PHP方法(后端)

也可以通过MediaWiki的钩子(Hook)来实现,在配置文件LocalSettings.php中加入如下代码:

$wgHooks['OutputPageBeforeHTML'][] = function(OutputPage $out, &$html) {
    global $wgUser;
    if (!$wgUser->isRegistered()) {
        // 匹配任意 class 包含 "hide-for-anon" 的 div,并移除其内容
        $html = preg_replace(
            '/<div class="hide-for-anon"[^>]*>.*?<\/div>/s',
            '<div class="anon-hidden-notice">请登录查看内容</div>',
            $html
        );
    }
    return true;
};

上述代码实现的原理就是在页面生成HTML前先进行检验,如果用户未注册,那么就将被<div class="hide-for-anon">……</div>包围的内容替换掉。比如“请登录查看内容”。
该方法亲测有效,但仅适用于简单文本。如果是模板并且有复杂文本内容的,它就无能为力了。
因此我们也可以更进一步,在LocalSettings.php中继续加入如下代码:

$wgHooks['ParserAfterParse'][] = function(Parser $parser, &$text, StripState $stripState) {
    global $wgUser;
    if (!$wgUser->isRegistered()) {
        // 移除模板输出的特定内容(需根据实际HTML结构调整正则)
        $text = preg_replace(
            '/<div class="template-sensitive-content">.*?<\/div>/is',
            '<div class="anon-notice">请登录查看内容</div>',
            $text
        );
    }
    return true;
};

它直接拦截了解析器,使得保存隐藏内容的模板不被解析展开,因此也就无法显示了。
因为是后端处理,所以使用钩子的方法都可以避免内容在源代码中暴露,相对而言要安全很多。

三、扩展方法

当然,我们也可以将上述的代码进一步优化生成一个自定义的扩展。但有没有现成的扩展可用呢?虽然没有直接满足要求的,不过我们仍可以通过一款名为UserFunctions的扩展,它增加了一些跟用户相关的解析函数,其中的{{#ifanon:then|else}}就可以用于本例(如果对用户有更明确的划分,也可以考虑{{#ifingroup:group|then|else}},它可以针对不同用户组来执行动作)。
该函数首先判断是否为匿名用户,如果是则执行then部分的内容,否则就执行else部分。所以我们只需要在需要隐藏的内容前添加该函数即可,例如:

{{#ifanon:|我是要隐藏的部分}}

由于我们不希望对匿名用户显示任何内容,所以then部分为空,而else则为文本内容“我是要隐藏的部分”。如果需要一些提醒也可以加一条消息,如:

{{#ifanon:本内容仅对注册用户开放|我是要隐藏的部分}}

到了这里,就可以新创建一个模板并加添加两个参数,比如{{#ifanon:{{{notice|}}}|{{{hidden|}}}}},那么以后遇到需要隐藏的内容就可以直接调用了。
最终对比效果如下:
注册用户显示内容.png

这是注册用户显示的内容,主题为Vector(2022)。

匿名用户显示内容.png
这是匿名用户显示的内容,主题为Timeless。

最后修改:2025 年 05 月 25 日
如果觉得我的文章对你有用,请随意赞赏