在使用易優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.373753.com/xinwendongtai/2119.html
版權聲明:站內所有文章皆來自網絡轉載,只供模板演示使用,并無任何其它意義!
上一篇: 易優cdn閱讀量不變的緩存規則
下一篇:沒有了