防注入第一道防线是输入过滤,核心是使输入在进入业务逻辑前丧失执行能力;应优先采用白名单校验、后端参数化查询与输出转义,并辅以请求级关键词拦截。

过滤外部输入的特殊字符是防注入的第一道防线,核心不是“删掉所有奇怪符号”,而是让输入在进入业务逻辑前就失去执行能力——尤其防止它被数据库或HTML引擎误当成代码解析。
用白名单比黑名单更可靠
黑名单容易漏(比如新出现的绕过方式),白名单直接定义“什么能进”。例如:
- 用户名只允许字母、数字、下划线,且长度3–16位:
/^[a-zA-Z0-9_]{3,16}$/ - 手机号只接受11位数字:
/^1[3-9]\d{9}$/ - 邮箱交由
FILTER_VALIDATE_EMAIL验证,不靠正则硬写
后端必须做转义,不能只靠前端
前端校验可被绕过,后端才是最终守门人:
- PHP中优先用
mysqli_real_escape_string()(配合当前连接字符集)或addslashes()(需确保magic_quotes_gpc未开启) - Java用
PreparedStatement,参数占位符(?)天然隔离数据与语句 - Python用
sqlite3的参数化查询或psycopg2的%s占位,避免.format()或f-string拼接SQL
输出时也要防二次注入
存进数据库的内容,如果后续直接echo到HTML里,可能触发XSS。所以:
- HTML上下文用
htmlspecialchars($data, ENT_QUOTES, 'UTF-8') - JavaScript字符串内插用
json_encode($data, JSON_UNESCAPED_UNICODE) - URL参数用
urlencode()或rawurlencode()
加一层请求级过滤更省心
在Web容器入口统一拦截高危模式,比如Spring Boot可写OncePerRequestFilter,Go可用中间件,PHP可通过$_GET/$_POST遍历检测:
- 匹配
union\s+select、drop\s+table、exec\s*\(|\bselect\b.*\bfrom\b等典型SQL关键字(注意大小写和空格变形) - 发现即返回400或记录日志并拒绝,不进入业务链路
- 注意:这层是补充,不能替代参数化查询











