在使用易优CMS(YouZhanCMS)进行站内搜索时,如果用户输入包含**特殊字符**(如:`+`、`-`、`*`、`%`、`'`、`"`、`(`、`)` 等),可能会导致SQL查询报错或返回异常结果。这是因为这些字符可能被误解析为SQL语法的一部分,从而引发SQL注入防护机制拦截或语法错误。以下是常见的解决方案:

单引号('):You have an error in your SQL syntax
双引号("):导致JSON解析错误
反斜杠(\):转义错误
百分号(%):SQL LIKE查询异常
尖括号(<>):XSS过滤冲突
特殊符号:&、#、+ 等URL编码问题
// 在搜索框提交前过滤
function filterSearchKeyword(keyword){
// 移除危险字符
var danger = /['"\\%;&=<>()#]/g;
keyword = keyword.replace(danger, '');
// 保留中英文数字和常用标点
keyword = keyword.replace(/[^\u4e00-\u9fa5a-zA-Z0-9\s,。!?、:;()《》]/g, '');
// 限制长度
if(keyword.length > 50) keyword = keyword.substr(0, 50);
return keyword.trim();
}
// 表单提交时调用
$('#search-form').submit(function(e){
var keyword = $('#search-input').val();
$('#search-input').val(filterSearchKeyword(keyword));
});// 文件:application/index/controller/Search.php
public function index(){
$keyword = input('keyword/s', '', 'trim');
// 方法1:严格过滤
$keyword = $this->filterKeyword($keyword);
// 方法2:URL解码后过滤
$keyword = urldecode($keyword);
$keyword = Htmlspecialchars($keyword, ENT_QUOTES, 'UTF-8');
// 方法3:正则保留安全字符
$keyword = preg_replace('/[^a-zA-Z0-9\x{4e00}-\x{9fa5}\-\_\s]/u', '', $keyword);
// 传递给模型
$result = model('app\common\model\Search')->search($keyword);
return json($result);
}
// 关键词过滤方法
private function filterKeyword($str){
if(empty($str)) return '';
// 移除SQL注入风险字符
$str = str_ireplace(
['select ', 'insert ', 'update ', 'delete ', 'drop ', 'union ', 'or ', 'and '],
'',
$str
);
// 转义特殊字符
$str = addslashes($str);
// 限制长度
if(mb_strlen($str, 'utf-8') > 100){
$str = mb_substr($str, 0, 100, 'utf-8');
}
return $str;
}<!-- 在搜索表单模板中增加防护 -->
<!-- 原位置:template/你的模板/search.htm -->
<form action="{:url('/search')}" method="get" onsubmit="return validateSearch()">
<input type="text" name="keyword" id="keyword"
placeholder="请输入关键词"
maxlength="50"
oninput="filterInput(this)">
<button type="submit">搜索</button>
</form>
<script>
function filterInput(input){
// 实时过滤
input.value = input.value.replace(/[<>'"\\&;#]/g, '');
}
function validateSearch(){
var keyword = document.getElementById('keyword').value;
if(!keyword.trim()){
alert('请输入搜索关键词');
return false;
}
if(keyword.length > 50){
alert('关键词过长');
return false;
}
return true;
}
</script>// 扩展ThinkPHP查询类
// 创建:application/common/Query.php
namespace app\common;
use think\db\Query;
class SafeQuery extends Query
{
/**
* LIKE查询安全处理
*/
public function whereLike($field, $value, $logic = 'AND')
{
// 转义LIKE特殊字符
$value = $this->escapeLike($value);
return parent::whereLike($field, $value, $logic);
}
/**
* 转义LIKE特殊字符
*/
protected function escapeLike($str)
{
if(is_string($str)){
$str = str_replace(
['\\', '%', '_'],
['\\\\', '\%', '\_'],
$str
);
}
return $str;
}
/**
* 安全条件查询
*/
public function whereSafe($field, $value, $logic = 'AND')
{
// 过滤危险值
if(is_string($value)){
$value = $this->filterValue($value);
}
return $this->where($field, $value, $logic);
}
protected function filterValue($value)
{
// 移除SQL关键字
$keywords = [
'select', 'insert', 'update', 'delete',
'drop', 'truncate', 'create', 'alter',
'union', 'or ', 'and ', 'xor',
';', '--', '/*', '*/', '#'
];
foreach($keywords as $keyword){
$value = str_ireplace($keyword, '', $value);
}
return trim($value);
}
}// 创建:application/http/middleware/SearchFilter.php namespace app\http\middleware; class SearchFilter { public function handle($request, \Closure $next) { // 只处理搜索请求 if($request->isGet() && strpos($request->pathinfo(), 'search') !== false){ $keyword = $request->param('keyword'); if($keyword){ // 安全过滤 $safeKeyword = $this->safeFilter($keyword); $request->withParam(['keyword' => $safeKeyword]); } } return $next($request); } protected function safeFilter($str) { // 1. URL解码 $str = urldecode($str); // 2. HTML实体转义 $str = htmlspecialchars($str, ENT_QUOTES, 'UTF-8'); // 3. 移除危险字符 $danger = [ "'", '"', '\\', ';', '=', '<', '>', '(', ')', '&', '#', '%', '*', '+', '!', '?', '~', '`', '|', '^' ]; $str = str_replace($danger, ' ', $str); // 4. 移除多余空格 $str = trim(preg_replace('/\s+/', ' ', $str)); // 5. 长度限制 if(mb_strlen($str, 'utf-8') > 100){ $str = mb_substr($str, 0, 100, 'utf-8'); } return $str; } } // 注册中间件:config/middleware.php return [ // 搜索过滤中间件 \app\http\middleware\SearchFilter::class ];
# 在server配置中添加
server {
# 搜索URL特殊字符过滤
if ($request_uri ~* "/search"){
# 检查危险字符
if ($arg_keyword ~* "([';\\\"%=<>\(\)])"){
return 400;
}
# 限制关键词长度
if ($arg_keyword ~ "^.{101,}$"){
return 413;
}
}
# 或者使用rewrite重写
location ~* ^/search {
# 对关键词进行URL重写
if ($args ~* "(keyword=.*[<>'].*)"){
rewrite ^ /search?keyword= break;
}
# 正常处理
try_files $uri $uri/ /index.php?s=$uri&$args;
}
}// 文件:app.php
'exception_handle' => 'app\common\exception\Handler',
// 创建异常处理类
namespace app\common\exception;
class Handler extends \think\exception\Handle
{
public function render($request, \Throwable $e)
{
// 数据库错误(通常是SQL注入导致)
if($e instanceof \think\db\exception\DbException){
// 记录日志
\think\facade\Log::error('搜索异常: ' . $e->getMessage());
// 对搜索请求返回友好错误
if(strpos($request->url(), 'search') !== false){
return json([
'code' => 0,
'msg' => '搜索关键词包含特殊字符,请重新输入',
'data' => [],
'total' => 0
]);
}
}
return parent::render($request, $e);
}
}// test_search.php
$testKeywords = [
"正常关键词",
"测试'单引号",
'测试"双引号',
"测试\\反斜杠",
"测试%百分号",
"测试_下划线",
"测试<尖括号>",
"测试&符号",
"测试;分号",
"测试=等号",
"测试(括号)",
"测试#井号",
"测试--注释",
"测试/*注释*/",
"测试 or 1=1",
"测试' and '1'='1",
"测试 union select",
"测试<script>alert(1)</script>",
"混合测试'\"\\%<>"
];
foreach($testKeywords as $keyword){
$url = "http://你的域名/search?keyword=" . urlencode($keyword);
$result = file_get_contents($url);
if(strpos($result, 'SQL syntax') !== false){
echo "❌ 失败: " . $keyword . "\n";
} else {
echo "✅ 通过: " . $keyword . "\n";
}
}# 使用ab测试 ab -n 1000 -c 10 "http://域名/search?keyword=测试'特殊字符" # 使用siege测试 siege -c 100 -r 10 "http://域名/search?keyword=测试<script>alert(1)</script>"
// 文件:application/common.php
/**
* 安全过滤搜索关键词
*/
function safe_search_keyword($keyword){
if(empty($keyword)) return '';
// 1. URL解码
$keyword = urldecode($keyword);
// 2. 基础过滤
$keyword = strip_tags($keyword);
$keyword = htmlspecialchars($keyword, ENT_QUOTES, 'UTF-8');
// 3. 移除SQL危险字符
$keyword = str_replace(
["'", '"', '\\', ';', '=', '--', '/*', '*/', '#'],
'',
$keyword
);
// 4. 移除SQL关键字
$sql_keywords = [
'/\bselect\b/i', '/\binsert\b/i', '/\bupdate\b/i', '/\bdelete\b/i',
'/\bdrop\b/i', '/\btruncate\b/i', '/\bcreate\b/i', '/\balter\b/i',
'/\bunion\b/i', '/\bor\b/i', '/\band\b/i'
];
$keyword = preg_replace($sql_keywords, '', $keyword);
// 5. 对LIKE查询转义
$keyword = str_replace(['%', '_'], ['\%', '\_'], $keyword);
// 6. 长度限制
if(mb_strlen($keyword, 'utf-8') > 100){
$keyword = mb_substr($keyword, 0, 100, 'utf-8');
}
return trim($keyword);
}// 所有搜索相关控制器添加
public function search(){
$keyword = input('keyword/s', '');
// 使用全局过滤函数
$safeKeyword = safe_search_keyword($keyword);
if(empty($safeKeyword)){
return $this->error('请输入有效的搜索关键词');
}
// 记录原始关键词(用于显示)
$this->assign('original_keyword', $keyword);
// 使用安全关键词搜索
$result = model('app\common\model\Search')->search($safeKeyword);
return $this->fetch('search', $result);
}<!-- 显示时使用原始关键词,搜索时使用过滤后关键词 -->
<script>
// 显示原始关键词
var originalKeyword = "{$original_keyword|raw}";
$('.search-result-title').text('搜索结果:' + originalKeyword);
// 搜索时过滤
$('#search-btn').click(function(){
var keyword = $('#keyword').val();
var safeKeyword = keyword.replace(/[<>'"\\%;&=#()]/g, '');
if(safeKeyword.length < 1){
alert('请输入有效关键词');
return false;
}
location.href = '/search?keyword=' + encodeURIComponent(safeKeyword);
});
</script>定期更新
保持易优CMS最新版本
关注官方安全更新
监控日志
# 监控搜索异常 tail -f runtime/log/*.log | grep -i "sql.*error\|exception" # 监控恶意搜索 awk '/search/ && /['\''";<>]/' access.log
WAF防护
配置Web应用防火墙规则
设置SQL注入防护
启用XSS防护
数据备份
定期备份数据库
备份修改的文件
# 如果问题紧急,可先临时屏蔽特殊字符搜索
cd /网站根目录
sed -i "s/\$keyword = input('keyword'/\/\/ 临时修复:禁止特殊字符\n \$keyword = input('keyword'/g" application/index/controller/Search.php
echo "修复完成,请刷新缓存"通过上述方案,可彻底解决易优站内搜索特殊字符报错问题。推荐使用全局过滤函数方案,既能保证安全性,又能提供良好的用户体验。
标签:
本文链接:http://www.7ov.cn/xinwendongtai/2119.html
版权声明:站内所有文章皆来自网络转载,只供模板演示使用,并无任何其它意义!
上一篇: 易优cdn阅读量不变的缓存规则
下一篇:没有了