在PHP中处理URL中的中文或特殊符号并用于MySQL查询时,需兼顾编码转换和安全防护。以下是完整解决方案:
🔐 一、URL参数安全处理(核心步骤)
- 获取并解码URL参数
使用urldecode()
或rawurldecode()
还原原始字符串,避免乱码:$keyword = urldecode($_GET['keyword']); // 解码中文或特殊符号
- 统一字符编码为UTF-8
防止因编码不一致导致乱码或查询失败:$keyword = mb_convert_encoding($keyword, 'UTF-8', 'auto'); // 自动检测源编码并转换
- 过滤危险字符
移除可能引发SQL注入的符号(如引号、分号):$safeKeyword = preg_replace('/[;\'"<>]/', '', $keyword); // 正则过滤高危字符
🛡️ 二、MySQL查询安全方案(3种方法)
✅ 方案1:预处理语句(强烈推荐)
$stmt = $mysqli->prepare("SELECT * FROM table WHERE column = ?");
$stmt->bind_param("s", $safeKeyword); // 自动处理特殊字符
$stmt->execute();
$result = $stmt->get_result();
优势:完全避免SQL注入,无需手动转义。
⚠️ 方案2:手动转义(兼容旧代码)
$escapedKeyword = $mysqli->real_escape_string($safeKeyword); // 转义特殊符号
$sql = "SELECT * FROM table WHERE column = '$escapedKeyword'";
注意:需确保数据库连接字符集为UTF-8(见下文)。
🚫 不推荐方案:直接拼接SQL
// 危险!以下写法存在注入漏洞:
$sql = "SELECT * FROM table WHERE column = '$_GET[keyword]'";
⚙️ 三、关键配置保障
- 设置PHP字符集
在脚本开头声明UTF-8编码:header('Content-Type: text/html; charset=utf-8'); // 确保输出正确 mb_internal_encoding('UTF-8'); // 设置内部编码
- 配置MySQL连接字符集
建立数据库连接后立即执行:$mysqli->set_charset("utf8"); // 关键!避免数据存储乱码
- 检查服务器环境
- Apache:在
.htaccess
添加AddDefaultCharset UTF-8
- Nginx:在配置中添加
charset utf-8;
- Apache:在
💎 四、完整流程示例
// 1. 获取并解码参数
$keyword = urldecode($_GET['keyword']);
// 2. 转换编码 + 过滤危险字符
$keyword = mb_convert_encoding($keyword, 'UTF-8', 'auto');
$safeKeyword = preg_replace('/[;\'"<>]/', '', $keyword);
// 3. 数据库安全查询
$mysqli = new mysqli("localhost", "user", "pass", "db");
$mysqli->set_charset("utf8"); // 关键配置!
$stmt = $mysqli->prepare("SELECT * FROM products WHERE name LIKE ?");
$searchTerm = "%$safeKeyword%";
$stmt->bind_param("s", $searchTerm);
$stmt->execute();
$result = $stmt->get_result();
while ($row = $result->fetch_assoc()) {
echo $row['name'];
}
⚠️ 避坑指南
- 不要依赖
addslashes()
此函数无法防御所有SQL注入类型。 - 避免双重编码
确保只调用一次urldecode()
,防止%25
等错误。 - 谨慎使用
iconv()
仅在确认源编码时使用(如iconv('GBK', 'UTF-8', $str)
)。