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

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

search.php 是织梦CMS的核心搜索功能文件,它负责接收用户的搜索请求、处理关键词、调用数据库、并最终展示搜索结果,理解这个文件对于自定义搜索功能、修改搜索逻辑或解决搜索问题至关重要。


search.php 的核心功能和工作流程

当用户在前台执行搜索时(点击一个带有 action="/search.php" 的表单),search.php 就会启动,其基本流程如下:

  1. 接收请求:获取用户通过GET或POST方式提交的搜索关键词 (keyword)。
  2. 初始化环境:加载必要的织梦核心文件,初始化数据库连接、全局变量等。
  3. 安全处理:对搜索关键词进行过滤,防止SQL注入和XSS攻击。
  4. 获取分页参数:获取当前是第几页 (pageno) 和每页显示多少条结果 (pagesize)。
  5. 调用搜索逻辑:这是最核心的一步,根据配置调用不同的搜索方法(默认是全文索引搜索)。
  6. 查询数据库:执行SQL查询,从主表 (dede_archives) 或全文索引表中获取匹配的文章ID列表。
  7. 获取结果详情:根据上一步得到的ID列表,批量查询文章的详细信息(标题、发布时间等)。
  8. 高亮关键词:将文章标题和内容中的搜索关键词用特定样式(如 <font color="red">)高亮显示。
  9. 处理分页:计算总页数,生成分页链接。
  10. 加载模板:加载 search.htm 模板文件。
  11. 输出结果:将处理好的数据(关键词、结果列表、分页信息等)赋值给模板变量,并最终渲染输出给用户。

search.php 文件结构详解

下面是一个典型的 search.php 文件代码结构,并附有详细注释。

<?php
/**
 * 织梦搜索文件
 *
 * @version        $Id: search.php 1 15:21 2010年7月12日Z tianya $
 * @package        DedeCMS.Site
 * @copyright      Copyright (c) 2007 - 2010, DesDev, Inc.
 * @license        http://help.dedecms.com/usersguide/license.html
 * @link           http://www.dedecms.com
 */
// 引入公共底层文件,这是织梦CMS的入口文件
require_once (dirname(__FILE__) . "/include/common.inc.php");
// 引入搜索相关的函数库
require_once DEDEINC."/search.class.php";
// --- 1. 获取并处理搜索关键词 ---
$keyword = empty($keyword) ? '' : trim($keyword);
$keyword = FilterSearch($keyword); // 调用内置函数进行安全过滤
// --- 2. 初始化搜索类 ---
// 实例化搜索类,传入关键词和每页显示数量
// $pagesize 通常在后台“核心设置”中配置,默认为10
$search = new Search($keyword, $pagesize);
// --- 3. 获取分页信息 ---
// 获取当前页码,默认为第1页
$pageno = isset($pageno) && is_numeric($pageno) ? intval($pageno) : 1;
// --- 4. 执行搜索查询 ---
// 调用GetResult()方法执行搜索,返回匹配的记录总数
$totalResult = $search->GetResult($pageno);
// 如果没有搜索结果,则直接输出并结束
if ($totalResult == 0)
{
    $dlist = new DataList();
    $dlist->SetTemplate($cfg_basedir . $cfg_templets_dir . "/search.htm");
    $dlist->Display();
    exit();
}
// --- 5. 获取并处理搜索结果列表 ---
// 获取当前页的结果数据
$list = $search->GetArcList();
// --- 6. 准备模板变量 ---
// 将搜索关键词和结果总数传递给模板
$oldkeyword = $keyword;
$keyword = htmlspecialchars($keyword); // 再次对关键词进行HTML实体转义,用于安全显示
$TypeLink = new TypeLink($typeid);
$typename = $TypeLink->GetTypeName();
// 获取分页链接
$plist = $search->GetPageList($list);
// 将所有变量放入一个数组中,方便模板调用
$addfields = array();
foreach($list as $k=>$v)
{
    // 可以在这里处理附加字段,如文章图片等
    $addfields[$k] = $v;
}
// --- 7. 加载并渲染模板 ---
$dlist = new DataList();
$dlist->SetTemplet($cfg_basedir . $cfg_templets_dir . "/search.htm"); // 指定搜索结果模板
$dlist->SetSource($list); // 设置数据源
$dlist->Display(); // 渲染并输出模板
?>

关键类和函数解析

  1. FilterSearch($keyword)

    • 位置include/filter.inc.php
    • 功能:对用户输入的搜索关键词进行过滤,移除一些可能导致安全问题的字符和词语,这是防止SQL注入和XSS攻击的第一道防线。
  2. new Search($keyword, $pagesize)

    • 位置include/search.class.php
    • 功能:实例化搜索核心类,这个类封装了所有搜索相关的逻辑。
    • $keyword: 搜索关键词。
    • $pagesize: 每页显示结果数,通常从全局配置 $cfg_search_pagesize 中获取。
  3. $search->GetResult($pageno)

    • 功能:执行搜索查询,并返回匹配的总记录数,这个方法会根据后台设置(是否开启全文索引)来决定是走全文索引还是 LIKE 查询。
    • 全文索引:效率极高,适合数据量大的网站,查询 dede_searchindex 表。
    • LIKE查询:效率较低,适合数据量小的网站或全文索引未开启时,直接查询 dede_archives 表的 titledescription 字段。
  4. $search->GetArcList()

    • 功能:在 GetResult() 找到文章ID后,这个方法会根据ID列表批量查询 dede_archives 表,获取文章的详细信息(标题、作者、发布时间、栏目ID等)并返回一个结果数组。
  5. $search->GetPageList($list)

    • 功能:根据总记录数和每页显示数量,生成分页链接字符串(如 上一页 1 2 3 4 5 下一页)。
  6. new DataList()

    • 功能:织梦的数据列表渲染类,它负责将PHP数据变量传递给HTML模板,并最终合并输出。

如何自定义搜索功能?

修改搜索结果模板

这是最常见的自定义需求,你只需要修改 templets/default/search.htm 文件。

search.htm 常用模板变量:

  • {dede:global name='keyword' function='RemoveXSS(@me)'/}: 安全显示搜索关键词。
  • {dede:global name='result'/}: 显示搜索结果总数,如“找到 15 条结果”。
  • {dede:list pagesize='10'}: 循环输出搜索结果列表。
    • [field:title/]: 文章标题(关键词已高亮)。
    • [field:arcurl/]: 文章链接。
    • [field:pubdate function="MyDate('Y-m-d',@me)"/]: 发布日期。
    • [field:description/]: 关键词已高亮)。
    • [field:typeid/]: 栏目ID。
    • [field:typename/]: 栏目名称。
  • {dede:pagelist listsize='4' listitem='info,index,end,pre,next,pageno'/}: 调用分页条。

修改搜索逻辑(进阶)

如果你需要修改搜索的匹配规则(只搜索特定栏目、搜索附加字段等),你需要修改 include/search.class.php 文件。

只搜索指定栏目(ID为1和2)的文章

search.class.phpGetKeywordList() 方法中,找到生成SQL查询的部分,在 WHERE 条件中增加栏目ID的限制。

// 原始代码可能类似
// $query = "SELECT aid FROM `{$this->AddTable}` WHERE {$this->GetCondition()}";
// 修改后
$addQuery = " AND typeid IN (1, 2)"; // 增加栏目ID限制
$query = "SELECT aid FROM `{$this->AddTable}` WHERE {$this->GetCondition()} $addQuery";

警告:直接修改核心文件可能会导致升级困难,建议做好备份或在二次开发时进行。

修改搜索表单

搜索的表单通常位于网站的页头 (header.htm) 或其他公共模板中,确保你的搜索表单 action 属性指向 search.php,并且输入框的 name 属性为 keyword

<form name="formsearch" action="/search.php">
    <input type="hidden" name="kwtype" value="0" />
    <input type="hidden" name="searchtype" value="titlekeyword" />
    <input name="keyword" type="text" class="search-keyword" />
    <button type="submit" class="search-submit">搜索</button>
</form>
  • kwtype: 0表示关键词搜索,1表示使用AND逻辑,2表示使用OR逻辑。
  • searchtype: titlekeyword 表示在标题和关键词中搜索,title 表示只在标题中搜索。

五. 常见问题与解决方案

  1. 搜索结果为空,但确定有相关文章

    • 原因:最常见的原因是全文索引未更新或损坏
    • 解决方案
      1. 登录织梦后台 -> 系统 -> 系统设置 -> SQL命令行工具
      2. 在命令行中执行以下命令,重建全文索引:
        ALTER TABLE `dede_archives` ADD FULLTEXT(`title`,`description`);
      3. 或者,在后台的“内容发布”或“搜索设置”里找到重建索引的选项。
  2. 搜索效率非常慢

    • 原因:网站数据量过大,且未开启全文索引,导致使用 LIKE 查询,全表扫描非常耗时。
    • 解决方案:按照上述方法,为 titledescription 字段添加全文索引。
  3. 想搜索文章内容(body)

    • 原因:默认搜索不包含文章正文内容,因为全文索引默认不包含 body 字段(该字段非常大,会严重影响索引效率)。
    • 解决方案
      1. 高风险方案:为 body 字段添加全文索引(ALTER TABLE ... ADD FULLTEXT(body)),这会极大消耗服务器资源和拖慢更新速度,不推荐大网站使用。
      2. 推荐方案:使用第三方搜索插件,如基于Elasticsearch或Sphinx的搜索方案,它们专门为海量数据搜索优化。

希望这份详细的解析能帮助你完全理解织梦的 search.php 文件!

-- 展开阅读全文 --
头像
dede list调用不成功,问题出在哪?
« 上一篇 01-03
C语言rand函数如何生成随机数?
下一篇 » 01-03
取消
微信二维码
支付宝二维码

目录[+]