You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PHP评论系统提交空白页 表单与验证码验证失效问题排查

问题根因排查
  • 空白页核心诱因:所有依赖Session的页面(评论表单页、提交处理页)未添加session_start(),验证码存储在Session中无法正常读取;所有header()跳转后未加exit;终止代码执行,逻辑穿透触发运行异常。
  • 校验逻辑缺陷:原有空值校验为合并判断,无法单独返回对应字段的定制提示;验证码校验未覆盖空输入场景,未做大小写兼容处理。
  • 代码逻辑漏洞:SQL语句直接拼接参数存在注入风险;评分字段未做默认值/范围校验,用户未选评分时传入空值触发数据库报错;验证码生成逻辑中Session赋值放在图片输出之后,HTTP头已发送无法写入Session,验证码永久失效。
  • 路径匹配错误:表单提交后跳转地址写为indexcomment.php,但实际表单页文件名为comments.php,路径不匹配触发404/空白页。

修复步骤&对应代码

1. 修复captcha.php验证码存储逻辑

将验证码存入Session的操作移到所有输出之前,新增大小写兼容处理:

<?php 
session_start();
$image_width = 280;
$image_height = 40;
$characters_on_image = 6;
$font = './fonts/monofont.ttf';
$possible_letters = '23456789bcdfghjkmnpqrstvwxyzBCDFGHJKLMNPQRSTVWXYZ';
$random_dots = 30;
$random_lines = 20;
$captcha_text_color="0x142864";
$captcha_noice_color = "0x142864";
$code = '';

$i = 0;
while ($i < $characters_on_image) { 
$code .= substr($possible_letters, mt_rand(0, strlen($possible_letters)-1), 1);
$i++;
}
// 提前存储验证码,禁止放在图片输出之后
$_SESSION['6_letters_code'] = strtolower($code);

$font_size = $image_height * .75;
$image = @imagecreate($image_width, $image_height);
$background_color = imagecolorallocate($image, 255, 255, 255);
$arr_text_color = hexrgb($captcha_text_color);
$text_color = imagecolorallocate($image, $arr_text_color['red'], $arr_text_color['green'], $arr_text_color['blue']);
$arr_noice_color = hexrgb($captcha_noice_color);
$image_noise_color = imagecolorallocate($image, $arr_noice_color['red'], $arr_noice_color['green'], $arr_noice_color['blue']);

for( $i=0; $i<$random_dots; $i++ ) {
imagefilledellipse($image, mt_rand(0,$image_width), mt_rand(0,$image_height), 2, 3, $image_noise_color);
}
for( $i=0; $i<$random_lines; $i++ ) {
imageline($image, mt_rand(0,$image_width), mt_rand(0,$image_height), mt_rand(0,$image_width), mt_rand(0,$image_height), $image_noise_color);
}

$textbox = imagettfbbox($font_size, 0, $font, $code); 
$x = ($image_width - $textbox[4])/2;
$y = ($image_height - $textbox[5])/2;
imagettftext($image, $font_size, 0, $x, $y, $text_color, $font , $code);

header('Content-Type: image/jpeg');
imagejpeg($image);
imagedestroy($image);

function hexrgb ($hexstr)
{
  $int = hexdec($hexstr);
  return array("red" => 0xFF & ($int >> 0x10), "green" => 0xFF & ($int >> 0x8), "blue" => 0xFF & $int);
}
?>

2. 修复post_comment.php提交处理逻辑

文件开头开启Session,拆分校验规则匹配定制提示,所有跳转后加终止逻辑,参数做基础过滤:

<?php 
session_start();
include_once 'controllers/Comment.php';
$com = new Comment();
if (isset($_POST['submit'])) {
    // 接收参数并做首尾去空、类型转换处理
    $name    = trim($_POST['name'] ?? '');
    $comment = trim($_POST['comment'] ?? '');
    $rating = intval($_POST['rating'] ?? 0);
    $captcha = trim($_POST['6_letters_code'] ?? '');

    // 逐字段校验,返回对应提示
    if(empty($_SESSION['6_letters_code']) || empty($captcha) || strtolower($_SESSION['6_letters_code']) != strtolower($captcha))
    {
        header('Location: comments.php?msg='.urlencode('Security code is invalid'));
        exit;
    }
    if (empty($name)) {
        header('Location: comments.php?msg='.urlencode('Name should not be empty'));
        exit;
    }
    if (empty($comment)) {
        header('Location: comments.php?msg='.urlencode('Text should not be empty'));
        exit;
    }
    if ($rating <1 || $rating>5) {
        header('Location: comments.php?msg='.urlencode('Please select a rating'));
        exit;
    }

    // 校验通过清除验证码,防止重复提交
    unset($_SESSION['6_letters_code']);
    $com->setData($name, $comment, $rating);
    if ($com->create()) {
        header('Location: comments.php?msg='.urlencode('Comment Posting Successfully'));
        exit;
    } else {
        header('Location: comments.php?msg='.urlencode('Failed to post comment, please try again'));
        exit;
    }
}
// 非提交请求直接跳回评论页
header('Location: comments.php');
exit;
?>

3. 修复Comment.php模型SQL注入风险

改用mysqli预处理语句,禁止直接拼接用户输入参数到SQL语句:

<?php 
include_once './database/DB.php';
class Comment
{
    private $db;
    private $name;
    private $comment;
    private $rating;
    private $table = "tbl_comments";

    public function __construct()
    {
        $this->db = new DB();
    }

    public function setData($name, $comment, $rating)
    {
        $this->name    = $name;
        $this->comment = $comment;
        $this->rating = $rating;
    }

    public function create()
    {
        // 预处理SQL防注入
        $stmt = $this->db->link->prepare("INSERT INTO $this->table(name, comment, rating, comment_time) VALUES(?, ?, ?, now())");
        $stmt->bind_param("ssi", $this->name, $this->comment, $this->rating);
        $result = $stmt->execute();
        $stmt->close();
        return $result;
    }

    public function index()
    {
        $query = "SELECT * FROM $this->table ORDER BY id DESC";
        $result = $this->db->select($query);
        return $result;
    }

    public function dateFormat($data)
    {
        date_default_timezone_set('Europe/Berlin');
        $date = date('M j, Y', time());
        return $date;
    }
}
?>

4. 修复comments.php页面依赖

在文件最开头(所有HTML输出之前)添加<?php session_start(); ?>,确保Session可正常读取;可给5星评分单选框加checked属性,避免用户漏选评分。


额外排查建议
  • 确认项目内文件相对路径正确,include引入文件路径错误也会触发空白页,可在php.ini中开启display_errors = On、error_reporting = E_ALL直接输出错误信息定位问题。
  • 确认fonts/monofont.ttf字体文件存在,字体缺失会导致验证码生成失败。

内容的提问来源于stack exchange,提问作者Christian

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.28 05:57:11