如何通过正则表达式校验防止网站注册页面的用户名SQL注入?

2026-04-27 21:421阅读0评论SEO资讯
  • 内容介绍
  • 文章标签
  • 相关推荐

本文共计825个文字,预计阅读时间需要4分钟。

如何通过正则表达式校验防止网站注册页面的用户名SQL注入?

用户提交的用户名如直接拼接进以下SQL语句,则可能导致攻击者输入如`admin' --`或`test' OR '1'='1`等恶意内容,从而绕过验证、写入异常数据,甚至拖库。这不是会不会发生的问题,而是只要没有防护,就一定会被扫到的问题。

只用正则校验用户名够不够防SQL注入

不够。正则只是第一道过滤,不是银弹:

  • 正则只能拦住明显恶意字符(比如单引号、分号、--/*),但绕过方式极多:Unicode 编码、宽字节注入、双写关键字(seleselectct)、空字节截断等
  • 正则规则太松 → 漏掉攻击载荷;太严 → 拦住合法用户名(如昵称含中文、emoji、连字符的用户)
  • 正则在前端做毫无意义,必须后端执行,且不能替代参数化查询

推荐组合策略: - 前端用正则简单提示(提升体验,不依赖它防攻击) - 后端用正则做初步清洗(如 preg_replace('/['";-+/*\]/', '', $username)) - 但最终插入数据库前,必须走参数化查询

PHP 中注册逻辑怎么写才真正安全

核心是:永远不用字符串拼接构造 SQL

错误写法(哪怕加了正则):

$username = $_POST['username']; $username = preg_replace('/['";-+/*\]/', '', $username); $sql = "INSERT INTO users (username) VALUES ('$username')"; // 危险!

正确写法(PDO + 预处理):

$pdo = new PDO($dsn, $user, $pass); $stmt = $pdo->prepare("INSERT INTO users (username) VALUES (?)"); $stmt->execute([$username]); // 用户输入原样传入,由驱动处理转义

注意点: - 不要自己写 mysql_real_escape_string —— 已废弃,且无法防御所有绕过 - 如果用 MySQLi,必须用 mysqli_prepare() + bind_param(),不能用 mysqli_real_escape_string() 拼接 - 正则清洗后的 $username 仍要进预处理,不要以为“洗过了就安全了”

正则表达式该匹配什么、不该匹配什么

目标不是“拦住所有坏字符”,而是“定义合法用户名范围”,再配合参数化兜底。

常见合理正则(以 PHP preg_match 为例): - 英文+数字+下划线:/^[a-zA-Z0-9_]{3,20}$/ - 支持中文和常见符号:/^[x{4e00}-x{9fa5}a-zA-Z0-9_-u3002uff1fuff01uff0cu3001uff1buff1au201cu201du2018u2019u300au300bu3008u3009u3010u3011u300cu300du2014u2026u300eu300f]{2,30}$/u - 必须加 ^$ 锚定,否则只校验开头一段

别踩的坑: - 不要用 stripslashesaddslashes 替代预处理 - 不要对已过滤的变量再做一次 htmlspecialchars() 再插库(这是防 XSS 的,和 SQL 注入无关) - 正则里别漏掉 Unicode 空格符(u00a0u200b),它们可能干扰解析但逃过基础正则

真正的防线不在正则有多密,而在于那条 prepare() 调用有没有被执行。只要没走到这一步,前面所有过滤都只是减缓攻击速度,不是阻止。

本文共计825个文字,预计阅读时间需要4分钟。

如何通过正则表达式校验防止网站注册页面的用户名SQL注入?

用户提交的用户名如直接拼接进以下SQL语句,则可能导致攻击者输入如`admin' --`或`test' OR '1'='1`等恶意内容,从而绕过验证、写入异常数据,甚至拖库。这不是会不会发生的问题,而是只要没有防护,就一定会被扫到的问题。

只用正则校验用户名够不够防SQL注入

不够。正则只是第一道过滤,不是银弹:

  • 正则只能拦住明显恶意字符(比如单引号、分号、--/*),但绕过方式极多:Unicode 编码、宽字节注入、双写关键字(seleselectct)、空字节截断等
  • 正则规则太松 → 漏掉攻击载荷;太严 → 拦住合法用户名(如昵称含中文、emoji、连字符的用户)
  • 正则在前端做毫无意义,必须后端执行,且不能替代参数化查询

推荐组合策略: - 前端用正则简单提示(提升体验,不依赖它防攻击) - 后端用正则做初步清洗(如 preg_replace('/['";-+/*\]/', '', $username)) - 但最终插入数据库前,必须走参数化查询

PHP 中注册逻辑怎么写才真正安全

核心是:永远不用字符串拼接构造 SQL

错误写法(哪怕加了正则):

$username = $_POST['username']; $username = preg_replace('/['";-+/*\]/', '', $username); $sql = "INSERT INTO users (username) VALUES ('$username')"; // 危险!

正确写法(PDO + 预处理):

$pdo = new PDO($dsn, $user, $pass); $stmt = $pdo->prepare("INSERT INTO users (username) VALUES (?)"); $stmt->execute([$username]); // 用户输入原样传入,由驱动处理转义

注意点: - 不要自己写 mysql_real_escape_string —— 已废弃,且无法防御所有绕过 - 如果用 MySQLi,必须用 mysqli_prepare() + bind_param(),不能用 mysqli_real_escape_string() 拼接 - 正则清洗后的 $username 仍要进预处理,不要以为“洗过了就安全了”

正则表达式该匹配什么、不该匹配什么

目标不是“拦住所有坏字符”,而是“定义合法用户名范围”,再配合参数化兜底。

常见合理正则(以 PHP preg_match 为例): - 英文+数字+下划线:/^[a-zA-Z0-9_]{3,20}$/ - 支持中文和常见符号:/^[x{4e00}-x{9fa5}a-zA-Z0-9_-u3002uff1fuff01uff0cu3001uff1buff1au201cu201du2018u2019u300au300bu3008u3009u3010u3011u300cu300du2014u2026u300eu300f]{2,30}$/u - 必须加 ^$ 锚定,否则只校验开头一段

别踩的坑: - 不要用 stripslashesaddslashes 替代预处理 - 不要对已过滤的变量再做一次 htmlspecialchars() 再插库(这是防 XSS 的,和 SQL 注入无关) - 正则里别漏掉 Unicode 空格符(u00a0u200b),它们可能干扰解析但逃过基础正则

真正的防线不在正则有多密,而在于那条 prepare() 调用有没有被执行。只要没走到这一步,前面所有过滤都只是减缓攻击速度,不是阻止。