环境

  • Typecho开源博客
  • Handsome主题(本文的第二个问题不知道是否跟主题有关,如果你没有使用这个主题那么本文的第二个修改并不完全适用你,不过可以作为参考,在其他主题下修改也是类似的)
  • Captcha验证码插件

Handsome主题下载,官网(收费)

https://www.ihewro.com/archives/489/

Captcha验证码插件下载地址

百度网盘: https://pan.baidu.com/s/1_dVLVoeKoefbxKGpXODnxg 提取码: xfnk

安装

  • 首先下载 Captcha 插件,将其上传至 typecho 的 /usr/plugins/ 目录下
  • 登陆博客后台,在控制台的插件项中中启用 Captcha 插件
  • 编辑博客当前使用的主题模板中的comments.php文件,在评论的表单位置也就是comments的form标签之间的任何你认为合适的地方,加上如下代码:
    <p><?php Captcha_Plugin::output(); ?></p>

    注意:如果你使用了handsome主题,那么应该修改这个文件:
    /usr/themes/handsome/component/comments.php
  • 保存文件,刷新网站即可看到效果。
    FireShot Capture 004 - 推荐一款适用于 Typecho 的评论验证码插件 - 向晚时光 - www.timelate.com.png

问题

启用这个插件貌似一切顺利,手机端也可以正常使用。可惜并不完美符合我的要求,有两个问题。

  1. 输入一次验证码成功评论之后typecho会刷新页面显示新评论。此时验证码图片并没有刷新,可是如果继续评论,输入同样的验证码会提示评论失败,此时只有手动F5刷新整个页面才会刷新正确的验证码。
  2. 输入错误的验证码只会提示评论不符合要求这个错误,并没有提示验证码错误。而且验证码区域并不会自动刷新,对用户不友好,用户不知道哪里出问题了。
  3. 默认的6个字符对用户不友好,我觉得2个字符足够挡住绝大多数的垃圾评论了。所以字符数要改成2。

修改

  1. 添加一个刷新按钮,让用户可以手动刷新验证码。
    文件:/usr/plugins/Captcha/Plugin.php
    修改output函数如下:

    public static function output()
    {
     echo '为防止恶意评论,评论前请输入下面图形中的两位英数字<br><img id="captchapic" src="' . Typecho_Common::url('/action/captcha', Helper::options()->index) 
     . '" title="' . _t('请点击按钮刷新验证码,点击图片刷新无效') . '" /><br />'
     . '<input type="text" class="captcha" name="captcha" />  '
     . '<input id="btnUpdCaptcha" type="button" onclick="document.getElementById(\'captchapic\').src = document.getElementById(\'captchapic\').src + \'?\' + Math.random()" value="刷新验证码"></input>';
    }
  2. 修改hansome主题的js文件,实现提交评论后自动刷新验证码。不论有没有成功。
    文件:/usr/themes/handsome/assets/js/core.min.js
    这里需要先将这个js文件格式化一下,因为作者已经用js混淆器给源代码js处理过,直接打开是天书。格式化方法很多就不介绍了。我使用的方法是使用vscode里面的一个格式化插件。
    格式化以后,找到下面这句代码
    if (!a(".comment-list", k).length)
    找到以后在这句话的前后修改成以下代码:

    For handsome主题 5.3.1

    // Added by mango
    // 提交评论后,不论成功与否,自动刷新验证码
    // 判断是否使用了验证码插件,如果有则自动刷新验证码
    // 这个btnUpdCaptcha需要跟插件里定义的刷新验证码按钮id一致
    if (a("#btnUpdCaptcha")) {
     // 调用刷新验证码按钮的onclick事件
     a("#btnUpdCaptcha").click();
    }
    // 下面这句话判断评论是否成功,如果失败了才进入里面的逻辑
    if (!a(".comment-list", k).length) {
    
     // Added by mango
     // 这里的a就是jquery,作者做了混淆
     // 判断k有没有包含错误消息,如果有则弹出这个错误消息
     // 目前知道的是插件在抛出Typecho_Widget_Exception异常带上的错误消息会以下面这种形式输出
     // <div class="container">
     //   Typecho_Widget_Exception异常带上的错误消息
     // </div>
     //debugger
     if (!a(".container", k).length) {
         // 进入到这里表示因为某种原因评论不成功
         return (
             a.message({
                 title: LocalConst.COMMENT_TITLE,
                 message: a.trim(a.parseHTML(k)[7].innerText),  // [7]目前还没找到好办法,强行取k这个页面的第7个元素,本来应该根据class取的
                 type: "error",
             }),
             a(h).removeClass("active"),
             a("#spin").removeClass("show inline"),
             c("#error"),
             !1
         );
     } else {
         // 如果没找到则返回handsome标准错误信息
         return (
             a.message({
                 title: LocalConst.COMMENT_TITLE,
                 message: LocalConst.COMMENT_CONTENT_LEGAL_INFO,
                 type: "error",
             }),
             a(h).removeClass("active"),
             a("#spin").removeClass("show inline"),
             c("#error"),
             !1
         );
     }
    }

    For handsome主题 6.0

    // Added by mango
    // 提交评论后,不论成功与否,自动刷新验证码
    // 判断是否使用了验证码插件,如果有则自动刷新验证码
    // 这个btnUpdCaptcha需要跟插件里定义的刷新验证码按钮id一致
    if (a("#btnUpdCaptcha")) {
     // 调用刷新验证码按钮的onclick事件
     a("#btnUpdCaptcha").click();
    }
    // 下面这句话判断评论是否成功,如果失败了才进入里面的逻辑
    if (!a(".comment-list", k).length) {
    
     // Added by mango
     // 这里的a就是jquery,作者做了混淆
     // 判断k有没有包含错误消息,如果有则弹出这个错误消息
     // 目前知道的是插件在抛出Typecho_Widget_Exception异常带上的错误消息会以下面这种形式输出
     // <div class="container">
     //   Typecho_Widget_Exception异常带上的错误消息
     // </div>
     //debugger
     if (!a(".container", k).length) {
         // 进入到这里表示因为某种原因评论不成功
         return (
             console.log(a("div", k)),
             ("undefined" != typeof content && "" != content) ||
                 (content = LocalConst.COMMENT_CONTENT_LEGAL_INFO),
             a.message({
                 title: LocalConst.COMMENT_TITLE,
                 message: a.trim(a.parseHTML(k)[7].innerText),  // [7]目前还没找到好办法,强行取k这个页面的第7个元素,本来应该根据class取的
                 type: "error",
             }),
             a(h).removeClass("active"),
             a("#spin").removeClass("show inline"),
             c("#error"),
             !1
             );
    
     } else {
         // 如果没找到则返回handsome标准错误信息
         return (
             console.log(a("div", k)),
             ("undefined" != typeof content && "" != content) ||
                 (content = LocalConst.COMMENT_CONTENT_LEGAL_INFO),
             a.message({
                 title: LocalConst.COMMENT_TITLE,
                 message: content,
                 type: "error",
             }),
             a(h).removeClass("active"),
             a("#spin").removeClass("show inline"),
             c("#error"),
             !1
             );
     }
    }
  3. 把验证码字符的个数从默认的6个改成2个。
    文件:/usr/plugins/Captcha/securimage2/securimage.php
    找到$this->code_length = 6;,改成2即可。

完成效果

  • 提供手动更新验证码按钮
  • 提交成功后自动刷新验证码
  • 没有输入或者输入错误会有错误提示并同时自动刷新验证码
  • 只要求输入2个字符
    FireShot Capture 005 - 解决不能访问json文件的一种方法 - 芒果爱吃胡萝卜 - blog.mangolovecarrot.net.png
Last modification:June 29, 2020
If you think my article is useful to you, please feel free to appreciate