[Typecho小试牛刀]Joe主题增加验证码(非插件方式)

[Typecho小试牛刀]Joe主题增加验证码(非插件方式)

苏苏
2022-05-14 / 17 评论 / 78 阅读 / 正在检测是否收录...
温馨提示:
本文最后更新于2023年04月06日,已超过848天没有更新,若内容或图片失效,请留言反馈。

刚刚接触Typecho,发现Joe主题不错,摸索了两天之后,发现Joe本身不支持评论验证码,就查阅资料,修改部分Joe主题文件,增加评论验证码功能。

当前版本

  • Typecho:1.2.0
  • Joe主题:7.3.6

目标

  • 非插件方式,简单实现原生支持验证码,过滤机器人灌水。

涉及文件

/Joe/core/function.php (必须)

  • 目的: 增加需要用到的函数
  • 增加如下3个函数
#生成验证码
function comment_protection_code(){
    $num1=rand(1,9);
    $num2=rand(1,9);
    $rand=rand(1,100)%3;
    switch($rand){
        case 0:
            $ret=$num1 + $num2;
            $symbol='+';
        break;
        case 1:
            $ret=$num1 - $num2;
            $symbol='-';
        break;
        case 2:
            $ret=$num1 * $num2;
            $symbol='×';
        break;
    }
    @session_start();
    $_SESSION['verify']=$ret;
    $_SESSION['verify_md5']=md5($num1.$num2);
    @session_write_close();
    echo "<input type=\"text\" autocomplete=\"off\" name=\"sum\" placeholder=\"$num1 $symbol $num2 = ?\" />";
    echo "<input type=\"hidden\" name=\"num1\" value=\"$num1\">\n";
    echo "<input type=\"hidden\" name=\"num2\" value=\"$num2\">";
}
#验证
function comment_protection_do(){
    /* 已登录,不检测验证码 */
    Typecho_Widget::widget('Widget_User')->to($current_user);
    if($current_user->hasLogin()){
        return 0;
    }
    @session_start();
    $case1=md5($_SESSION['verify']) != md5($_POST['sum']);
    $case2=$_SESSION['verify_md5'] != md5($_POST['num1'].$_POST['num2']);
    $debug=$_SESSION['verify'].$_SESSION['verify_md5'].$case1. $case2;
    @session_write_close();
    if($case1 || $case2){
        throw new Typecho_Widget_Exception(_t('验证码错误,建议先复制评论,然后刷新重试!','评论失败'), 200);
    }
    return 0;
}
#判断路由用到
function endsWith($haystack, $needle){
    return $needle === '' || substr_compare($haystack, $needle, -strlen($needle)) === 0;
}

/Joe/core/core.php (必须)

  • 目的: 挂载验证函数
  • 搜索函数 themeInit ,将如下代码粘贴到函数内
#仅在提交评论时生效
if(endsWith($self->request->getPathInfo(), '/comment')){
    $comment = comment_protection_do();
}

/Joe/public/comment.php (必须)

  • 目的: 增加验证码输入框
  • 搜索 输入网址 ,在它的下方增加一个兄弟节点,用来输入验证码
...
<div class="list">
    <input type="text" autocomplete="off" name="url" placeholder="请输入网址(非必填)..." />
</div>
#上方为原始代码
#下方为新增
<!-- @苏苏修改 增加验证码输入框-->
<div class="list">
    <?php comment_protection_code();?>
</div>

/Joe/assets/js/joe.global.js (必须)

  • 目的: 在提交评论时,增加验证码校验参数
  • 打开未压缩版js文件,搜索激活评论提交,用下方代码替换,然后压缩后替换同文件夹的joe.global.min.js
    /* 激活评论提交 已修改 */
    {
        if ($('.joe_comment').length) {
            let isSubmit = false;
            $('.joe_comment__respond-form').on('submit', function (e) {
                e.preventDefault();
                const action = $('.joe_comment__respond-form').attr('action') + '?time=' + +new Date();
                const type = $('.joe_comment__respond-form').attr('data-type');
                const parent = $('.joe_comment__respond-form').attr('data-coid');
                const author = $(".joe_comment__respond-form .head input[name='author']").val();
                const _ = $(".joe_comment__respond-form input[name='_']").val();
                const mail = $(".joe_comment__respond-form .head input[name='mail']").val();
                const url = $(".joe_comment__respond-form .head input[name='url']").val();
                const sum = $(".joe_comment__respond-form .head input[name='sum']").val();
                const num1 = $(".joe_comment__respond-form .head input[name='num1']").val();
                const num2 = $(".joe_comment__respond-form .head input[name='num2']").val();
                let text = $(".joe_comment__respond-form .body textarea[name='text']").val();
                if (sum === '') return Qmsg.info('请输入验证信息!');
                if (author.trim() === '') return Qmsg.info('请输入昵称!');
                if (!/\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*/.test(mail)) return Qmsg.info('请输入正确的邮箱!');
                if (type === 'text' && text.trim() === '') return Qmsg.info('请输入评论内容!');
                if (type === 'draw') {
                    const txt = $('#joe_comment_draw')[0].toDataURL('image/webp', 0.1);
                    text = '{!{' + txt + '}!} ';
                }
                if (isSubmit) return;
                isSubmit = true;
                $('.joe_comment__respond-form .foot .submit button').html('发送中...');
                $.ajax({
                    url: action,
                    type: 'POST',
                    data: { author, mail, text, parent, url, num1, num2, sum, _ },
                    dataType: 'text',
                    success(res) {
                        let arr = [],
                            str = '';
                        arr = $(res).contents();
                        Array.from(arr).forEach(_ => {
                            if (_.parentNode.className === 'container') str = _;
                        });
                        if (!/Joe/.test(res)) {
                            Qmsg.warning(str.textContent.trim() || '');
                            isSubmit = false;
                            $('.joe_comment__respond-form .foot .submit button').html('发表评论');
                        } else {
                            window.location.reload();
                        }
                    },
                    error(res) {
                        isSubmit = false;
                        $('.joe_comment__respond-form .foot .submit button').html('发表评论');
                        Qmsg.warning('发送失败!请刷新重试!');
                    }
                });
            });
        }
    }

自定义css(可选)

  • 目的: 在输入框左侧增加竖形分割线,统一外观
  • 添加方式:Joe主题设置->全局设置->自定义CSS,粘贴下面的代码
/*验证码处css*/
@media (min-width: 768px){.joe_comment__respond-form .head .list:nth-child(4){position:relative}.joe_comment__respond-form .head .list:nth-child(4)::before{content:'';position:absolute;top:50%;transform:translateY(-50%);width:1px;height:15px;background:var(--classA)}.joe_comment__respond-form .head .list:nth-child(4)::before{left:0}}

最终效果

2

评论 (17)

取消
  1. 头像
    xcshare
    Windows 7 · MicroSoft Edge
    @

    表情
    原来是我在function中发错位置了,已经按照文章的指引,顺利添加成功,感谢!
    另外,就是这段CSS放在后台,我的主题评论会显示空白,我就放进了joe.normalize.min.css中,就正常了。
    这计算还有负值啊,建议这个修复一下。

    回复
    1. 头像
      苏苏 作者
      Android · MicroSoft Edge(M)
      @ xcshare
      css这个确实奇怪,按道理来了讲和位置无关;负数这个不是bug,改起来也很简单,把function comment_protection_code里面
      $rand=rand(1,100)%3改成%2,case 1代码段删掉,case 2改成case 1即可
      回复
      1. 头像
        xcshare
        Windows 7 · MicroSoft Edge
        @ 苏苏

        这个策略是删除了减法吗?有没有办法来个判断,num1>num2 则可以使用减法?表情乱提了,可能比较麻烦

        回复
        1. 头像
          苏苏 作者
          Android · MicroSoft Edge(M)
          @ xcshare

          那不就脱了裤子放屁了表情

          回复
  2. 头像
    xcshare
    Windows 7 · MicroSoft Edge
    @

    你好,按照你上面的代码,我的老是报错,我也是joe主题,comment文件的代码是这个:
    https://pic.fuuuy.cn/i/2022/09/18/63267cc7ab784.jpg
    应该怎么改呢

    回复
    1. 头像
      苏苏 作者
      Android · MicroSoft Edge(M)
      @ xcshare

      报错提示什么?

      回复
  3. 头像
    vian
    Windows 10 · Google Chrome
    @

    遇到问题了 我上午测试评论时是登陆状态 评论没问题
    下午我测试了访客评论 即便输入正确验证码也会提示验证码错误 关键是控制台也没看到报错表情

    回复
  4. 头像
    vian
    Windows 10 · Google Chrome
    @

    我写一篇转载可以吗表情

    回复
    1. 头像
      苏苏 作者
      Linux · MicroSoft Edge
      @ vian

      可以转载,注明来源即可

      回复
      1. 头像
        vian
        Windows 10 · Google Chrome
        @ 苏苏

        OK表情

        回复
  5. 头像
    vian
    Windows 10 · Google Chrome
    @

    问题解决了 是我自己笨蛋了 哈哈 多谢教程表情

    回复
    1. 头像
      苏苏 作者
      Windows 10 · MicroSoft Edge
      @ vian

      不客气,解决就好表情

      回复
      1. 头像
        vian
        Windows 10 · Google Chrome
        @ 苏苏

        多谢你写的教程表情

        回复
  6. 头像
    vian
    Windows 10 · Google Chrome
    @

    请问你用什么压缩的 我这压缩完报错 提示 Invalid or unexpected token 表情

    回复
    1. 头像
      苏苏 作者
      Windows 10 · MicroSoft Edge
      @ vian

      已发送邮件,我用的VS Codse 的JS & CSS Minifier (Minify)插件

      回复
  7. 头像
    魏小白
    Windows 10 · FireFox
    @

    7.3.7 版本验证码没生效

    回复
    1. 头像
      苏苏 作者
      Windows 10 · MicroSoft Edge
      @ 魏小白

      不显示输入框,还是验证码无论是否输入正确都提示验证码错误,或者验证码输入错误仍然可以正常发表评论?

      回复