菜鸟站长
个人博客主题模板、应用插件、功能开发技术资源聚合分享网站

Typecho 评论加上图片验证码

发布者:菜鸟站长  发布日期:2023-12-27  更新日期:2023-12-27  人气指数:205

给Typecho评论加计算验证码应该到处都是了吧。

最基础版本

最基础的验证码原理不复杂,给评论框加上两个隐藏参数mp-num1mp-num2,给用户一个看得见的输入框mp-sum,提交评论的时候检查mp-num1+mp-num2是否和mp-sum一致,不一致就拒绝提交。

修改comments.php,假如上述三个参数

<?php $num1 = rand(1, 49);$num2 = rand(1, 49); ?>
<span><?php _e("验证码 %s + %s =", $num1, $num2); ?></span>
<input type="text" name="mp-sum" placeholder="<?php _e("请输入计算结果") ?>" required>
<input type="hidden" name="mp-num1" value="<?php echo $num1; ?>">
<input type="hidden" name="mp-num2" value="<?php echo $num2; ?>">

当然了,光有前端是不行的。给提交评论接口加个验证码校验函数,修改functions.php,加入下面的代码

Typecho_Plugin::factory('Widget_Feedback')->comment = ['XComment', 'feedbackFilter'];
class XComment {
/**
* 获取 Request 实例
* @return \Typecho\Widget\Request|Typecho_Request
*/
public static function getRequest()
{
if (class_exists('Typecho\Widget\Request')) {
return new Typecho\Widget\Request(Typecho\Request::getInstance());
}
return Typecho_Request::getInstance();
}
/**
* 评论发布钩子
* @param $comment
* @param $archive
* @return mixed
* @throws \Typecho\Widget\Exception
*/
public static function feedbackFilter($comment, $archive)
{
$request = self::getRequest();
/** 评论必须回答问题 */
$sum = $request->filter('intval')->get('mp-sum');
$num1 = $request->filter('intval')->get('mp-num1');
$num2 = $request->filter('intval')->get('mp-num2');
if ($sum !== ($num1 + $num2)) {
throw new \Typecho\Widget\Exception(_t('对不起: 验证码错误,请<a href="javascript:history.back(-1)">返回</a>重试。', '评论失败'));
}
}
}

这样就可以防住一部分特别低级的机器人了。

验证码输出为 图片

因为这套代码流传挺广的,容易被脚本小子一锅端,可以考虑把验证码输出为 图片 。原理也不复杂,调用PHP的GD库把文本转成图片就行。

function textToPngBase64($text, string $font = 'comic.ttf', int $size = 16)
{
    if (!function_exists('imagettfbbox')) {
        return false;
    }
    // 字体存放在主题目录的fonts文件夹下
    $font_path = Helper::options()-&gt;themeFile('fonts/' . $font, Helper::options()-&gt;theme);
    if (!is_file($font_path)) {
        // 确保字体存在
        return false;
    }
    // 计算文本的宽度和高度
    $bbox = imagettfbbox($size, 0, $font_path, $text);
    $text_width = $bbox[2] - $bbox[0];
    $text_height = $bbox[1] - $bbox[7];

    // 创建一个自适应宽度的空白图像
    $width = $text_width + 20; // 添加一些额外的宽度以使图像更美观
    $height = $text_height + 20; // 添加一些额外的高度以使图像更美观
    // 创建 PNG透明底 画布
    $canvas = imagecreatetruecolor($width, $height);
    // 为一幅图像分配颜色和透明度
    $background = imagecolorallocatealpha($canvas, 255, 255, 255, 0);
    // 区域填充背景颜色
    imagefill($canvas, 0, 0, $background);
    // 将某个颜色定义为透明色
    imagecolortransparent($canvas, $background);
    $font_color = imagecolorallocate($canvas, 0, 0, 0);
    imagettftext($canvas, $size, 0, 10, $text_height + 10, $font_color, $font_path, $text);

    $lines = rand(5, 10);
    // 循环添加干扰线
    for ($i = 0; $i &lt; $lines; $i++) {
        // 定义干扰线的颜色
        $line_color = imagecolorallocate($canvas, rand(0, 255), rand(0, 255), rand(0, 255));

        // 随机生成干扰线的起点和终点坐标
        $x1 = rand(0, imagesx($canvas));
        $y1 = rand(0, imagesy($canvas));
        $x2 = rand(0, imagesx($canvas));
        $y2 = rand(0, imagesy($canvas));

        // 添加干扰线
        imageline($canvas, $x1, $y1, $x2, $y2, $line_color);
    }

    // 将图像输出为PNG格式,并将结果以Base64编码的方式返回
    ob_start();
    imagepng($canvas);
    $image_data = ob_get_clean();
    $base64 = base64_encode($image_data);

    // 释放图像资源
    imagedestroy($canvas);

    // 返回PNG图像的Base64编码
    return 'data:image/png;base64,' . $base64;
}

把上面的函数放到functions.php,就可以在comments.php里调用输出了

<?php $num1 = rand(1, 49);$num2 = rand(1, 49);
$text = _t("验证码 %s + %s =", $num1, $num2);
$src = textToPngBase64($text);
if ($src): ?>
<img src="<?php echo $src; ?>" />
<?php else: ?>
<span><?php echo $text; ?></span>
<?php endif; ?>
<input type="text" name="mp-sum" placeholder="<?php _e("请输入计算结果") ?>" required>
<input type="hidden" name="mp-num1" value="<?php echo $num1; ?>">
<input type="hidden" name="mp-num2" value="<?php echo $num2; ?>">

加密校验参数

上面只是把验证码提示换成了图片,但是校验参数还是明文的,不太好,加密校验参数很简单,就是不往用户那边发数字,去掉mp-num1np-num2,那你会问我那怎么对应答案呢?计算机行业的大佬(具体是谁 CHATGPT3.5也不知道)给你想好了,使用session存放这个验证码,session是由服务器端维护的用户会话数据。用人话说就是档案袋,你有,但是你不能摸。

$_SESSION['mp-sum'] = $num1 + $num2;

验证

class XComment {
...
public static function feedbackFilter($comment, $archive)
{
$request = self::getRequest();
/** 评论必须回答问题 */
$sum = $request->filter('intval')->get('mp-sum');
if ($sum !== $_SESSION['mp-sum']) {
throw new \Typecho\Widget\Exception(_t('对不起: 验证码错误,请<a href="javascript:history.back(-1)">返回</a>重试。', '评论失败'));
}
}
}
本文检索关键词:typecho教程 , 图片验证码

菜鸟站长推荐教程



添加新评论 »

icon_mrgreen.pngicon_neutral.pngicon_twisted.pngicon_arrow.pngicon_eek.pngicon_smile.pngicon_confused.pngicon_cool.pngicon_evil.pngicon_biggrin.pngicon_idea.pngicon_redface.pngicon_razz.pngicon_rolleyes.pngicon_wink.pngicon_cry.pngicon_surprised.pngicon_lol.pngicon_mad.pngicon_sad.pngicon_exclaim.pngicon_question.png