织梦count.php漏洞如何修复?

99ANYc3cd6
预计阅读时长 15 分钟
位置: 首页 织梦建站 正文

count.php 的核心作用

count.php 的中文意思是“计数器”,它的唯一核心功能就是更新文章或栏目等内容的浏览次数(点击数)

织梦count.php
(图片来源网络,侵删)

当你访问一篇新闻文章时,页面加载完成后,会向服务器发起一个异步请求(通常是AJAX),这个请求的目标就是 count.php,并传递文章ID等信息。count.php 收到请求后,会将对应文章的浏览次数在数据库中加1。

为什么需要单独一个文件? 这种设计模式非常经典,主要是为了性能优化用户体验

  • 用户体验:更新浏览次数是一个需要写入数据库的操作,可能会比读取页面内容慢一些,如果这个操作和页面主内容加载放在一起,会拖慢用户看到页面的速度,通过异步请求,用户可以立即看到文章内容,而浏览次数的更新在后台悄悄完成,用户无感知。
  • 性能优化:将数据库写入操作与页面渲染分离,减轻了页面请求的压力,即使计数器更新偶尔失败,也不会影响用户正常浏览文章。

工作流程详解

下面是 count.php 完整的工作流程:

  1. 触发

    织梦count.php
    (图片来源网络,侵删)
    • 用户在浏览器中点击一篇带有“浏览次数”显示的文章链接。
    • 页面加载完成后,页面中的JavaScript代码会向 count.php 发送一个AJAX请求,这个请求通常会附带一些参数,最常见的是:
      • view:操作类型,固定为 click(表示点击计数)。
      • aid:文章的ID(Archives ID)。
      • mid:模型的ID(Model ID)。
  2. 接收请求

    • count.php 脚本被服务器执行。
    • 它首先会接收并解析从AJAX请求中传来的 aid(文章ID)。
  3. 安全校验

    • 这是非常关键的一步,防止恶意刷点击数。
    • 它会检查请求来源是否合法,通常的做法是判断HTTP请求头中的 Referer 字段,看它是否来自本站的域名。
    • 它还会检查请求的频率,防止短时间内大量请求(DDoS攻击)。
  4. 数据库操作

    • 如果安全校验通过,count.php 会连接到网站的数据库。
    • 执行一条 UPDATE SQL语句,将 dede_archives(文章表)中对应 aid 的记录的 click(点击数)字段值加1。
    • SQL语句类似这样:UPDATEdede_archivesSETclickclick+ 1 WHEREid= '文章ID'
  5. 返回结果

    • 数据库操作完成后,count.php 会向浏览器返回一个简单的响应,通常是 success1,表示计数成功,AJAX脚本接收到这个响应后,通常会更新页面上显示的浏览次数。

count.php 文件源码解析(以织梦DedeCMS 5.7为例)

下面是一个典型的 count.php 文件源码,并附上逐行注释:

<?php
/**
 * 织梦CMS浏览次数统计文件
 */
// 1. 安全检查:防止直接通过URL访问
if (!defined('DEDEINC')) {
    exit("Request Error!");
}
// 2. 引入数据库配置和公共函数
require_once(DEDEINC . '/dedevote.class.php');
// 3. 获取并处理AJAX请求参数
$aid = isset($aid) && is_numeric($aid) ? $aid : 0;
// 如果没有获取到有效的文章ID,则直接退出
if ($aid == 0) {
    exit();
}
// 4. 安全校验:检查Referer(来源页面)
$referer = isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : '';
// 获取当前网站的主域名
$main_domain = preg_replace('/^https?:\/\//', '', $cfg_basehost);
// 如果来源页面不是本站的,则不进行计数
if ($referer != '' && strpos($referer, $main_domain) === false) {
    exit();
}
// 5. 执行数据库更新操作
// 获取当前文章的点击数
$row = $dsql->GetOne("SELECT click FROM `#@__archives` WHERE id='$aid'");
if (is_array($row)) {
    $click = $row['click'] + 1;
    // 更新数据库中的点击数
    $dsql->ExecuteNoneQuery("UPDATE `#@__archives` SET click='$click' WHERE id='$aid'");
}
// 6. 返回成功状态给前端
echo 'success';
?>

常见问题与解决方案

问题1:点击数不增加怎么办?

这是最常见的问题,排查步骤如下:

  1. 检查文件是否存在:确认 /include/count.php 文件是否存在于你的服务器上,有时可能被误删。
  2. 检查文件权限:确保 count.php 文件和 data 目录(存放缓存等)有正确的读写权限(通常是 755644)。
  3. 检查JS/AJAX是否被禁用:如果用户浏览器禁用了JavaScript,那么AJAX请求无法发送,计数器自然不会工作,但这对所有用户都生效的情况较少。
  4. 检查前端模板:打开文章详情页的模板文件(通常是 article_article.htm),查找是否有调用浏览次数的代码,以及是否有触发 count.php 的JavaScript代码,寻找类似 $.get("/include/count.php?...") 的代码。
  5. 检查浏览器控制台:按F12打开开发者工具,切换到 "Network" (网络) 标签,然后刷新页面,看看有没有一个名为 count.php 的请求,以及它的状态码是否为 200 OK,如果状态码是 404 Not Found,说明文件找不到;如果是 403 Forbidden,是权限问题。
  6. 检查安全插件或服务器规则:某些WAF(Web应用防火墙)或服务器的安全规则(如.htaccess)可能会拦截对 count.php 的请求,特别是当它检测到大量请求时。
  7. 数据库问题:检查数据库连接是否正常,#@__archives 表是否存在,以及 click 字段是否是数字类型。

问题2:如何修改计数逻辑?

如果你想进行二次开发,比如修改计数方式,可以编辑 count.php 文件。

  • 示例1:增加防刷机制 你可以在写入数据库前,增加对用户IP或Cookie的判断,限制同一个用户在一段时间内只能计数一次。

    // 在执行SQL前增加如下逻辑
    $ip = GetIP();
    $cookie_name = 'dede_click_'.$aid;
    if(isset($_COOKIE[$cookie_name])){
        exit(); // 如果已经点击过,直接退出
    }
    // ... 执行数据库更新 ...
    // 更新成功后,设置一个Cookie,有效期例如为24小时
    setcookie($cookie_name, '1', time() + 3600 * 24, '/');
  • 示例2:修改计数字段 如果你想把点击数存在另一个字段,click_new,只需修改SQL语句即可。

    // 原SQL
    // $dsql->ExecuteNoneQuery("UPDATE `#@__archives` SET click='$click' WHERE id='$aid'");
    // 修改后的SQL
    $dsql->ExecuteNoneQuery("UPDATE `#@__archives` SET click_new='$click' WHERE id='$aid'");

count.php 是织梦CMS一个设计巧妙的后台处理脚本,它通过异步请求的方式,优雅地实现了内容浏览次数的统计,既保证了用户体验,又优化了系统性能。

在排查点击数问题时,应遵循“前端检查 -> 后端文件 -> 服务器环境 -> 数据库”的顺序进行排查,对于开发者而言,count.php 也是一个进行数据统计相关功能二次开发的理想入口点。

-- 展开阅读全文 --
头像
dede文章页调用多张图片
« 上一篇 02-12
织梦login.php存在哪些安全隐患?
下一篇 » 02-12
取消
微信二维码
支付宝二维码

目录[+]