本文目录导读:

脚本过滤非法请求参数是保障Web应用安全的重要环节,核心思想是不信赖任何来自客户端的数据,采用 白名单(只允许合法字符) 比 黑名单(禁止非法字符) 更安全。
以下从三个层面提供脚本方案:通用逻辑、代码实现(Node.js/Python/Java示例)、以及具体的防御场景。
通用过滤逻辑(建议集成到中间件)
一个健壮的过滤脚本通常包含以下步骤:
- 输入清洗(Sanitization):删除或编码危险的字符。
- 输入验证(Validation):检查格式、类型、长度、范围。
- 参数类型强制转换:确保
id是整数,page是数字。
代码实现示例
Node.js (Express 中间件示例)
使用 validator 库和 xss 库进行清洗。
// 安装: npm install validator xss
const validator = require('validator');
const xss = require('xss');
// 过滤函数:对传入的 query/body 进行递归清洗
function sanitizeObject(obj) {
if (typeof obj === 'string') {
// 1. 去除首尾空格(Trim)
let clean = obj.trim();
// 2. 转义 HTML 特殊字符,防止 XSS
clean = xss(clean);
// 3. 去除控制字符(ASCII 0-31, 127)
clean = clean.replace(/[\x00-\x1f\x7f]/g, '');
return clean;
} else if (Array.isArray(obj)) {
return obj.map(item => sanitizeObject(item));
} else if (obj && typeof obj === 'object') {
const cleaned = {};
for (const [key, value] of Object.entries(obj)) {
// 过滤参数名:只允许字母、数字、下划线、中划线
if (!/^[a-zA-Z0-9_-]+$/.test(key)) {
delete obj[key]; // 删除非法的参数名
continue;
}
cleaned[key] = sanitizeObject(value);
}
return cleaned;
}
return obj;
}
// Express 中间件
function paramFilter(req, res, next) {
try {
req.query = sanitizeObject(req.query);
req.body = sanitizeObject(req.body);
// 检查关键参数类型
if (req.query.id && !validator.isInt(req.query.id)) {
return res.status(400).json({ error: 'Invalid ID format' });
}
next();
} catch (error) {
return res.status(400).json({ error: 'Parameter sanitization failed' });
}
}
// 应用中间件(在路由之前)
app.use(paramFilter);
Python (Flask 示例)
使用 bleach 库清洗 HTML,使用正则校验。
import re
import bleach
from flask import request, abort, jsonify
# 白名单模式:只允许指定的字符
ALLOWED_PATTERN = re.compile(r'^[a-zA-Z0-9_\-\s\.\,\!\?]*$')
def sanitize_param(value, max_length=255):
"""清洗单个参数"""
if not isinstance(value, str):
return value
# 1. 截断长度(防止DOS攻击)
value = value[:max_length]
# 2. 去除不可见控制字符(除了空格和换行)
value = re.sub(r'[\x00-\x08\x0B\x0C\x0E-\x1F\x7F]', '', value)
# 3. 清洗HTML标签(防止XSS),允许一些安全标签如 <b>, <i>
value = bleach.clean(value, tags=['b', 'i', 'u'], strip=True)
return value
def filter_params():
"""过滤请求参数"""
filtered = {}
for key, value in request.args.items():
# 过滤参数名:只允许字母数字
if not re.match(r'^[a-zA-Z0-9_]+$', key):
continue # 跳过非法参数名
# 对值进行清洗
filtered[key] = sanitize_param(value)
return filtered
# 在视图函数中使用
@app.route('/search')
def search():
params = filter_params()
keyword = params.get('keyword', '')
# 具体业务验证
if len(keyword) > 0 and not ALLOWED_PATTERN.match(keyword):
abort(400, description="Keyword contains invalid characters")
return jsonify({"status": "ok", "keyword": keyword})
Java (Spring Boot 统一过滤)
创建自定义的 HttpServletRequestWrapper 或使用过滤器。
import org.springframework.web.util.HtmlUtils;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.util.regex.Pattern;
public class XssHttpServletRequestWrapper extends HttpServletRequestWrapper {
private static final Pattern[] XSS_PATTERNS = new Pattern[]{
Pattern.compile("<script>(.*?)</script>", Pattern.CASE_INSENSITIVE),
Pattern.compile("onload=(.*?) ", Pattern.CASE_INSENSITIVE | Pattern.DOTALL),
Pattern.compile("eval\\((.*?)\\)", Pattern.CASE_INSENSITIVE | Pattern.DOTALL)
};
public XssHttpServletRequestWrapper(HttpServletRequest request) {
super(request);
}
@Override
public String getParameter(String name) {
String value = super.getParameter(name);
if (value == null) return null;
return cleanXSS(value);
}
@Override
public String[] getParameterValues(String name) {
String[] values = super.getParameterValues(name);
if (values == null) return null;
String[] cleaned = new String[values.length];
for (int i = 0; i < values.length; i++) {
cleaned[i] = cleanXSS(values[i]);
}
return cleaned;
}
private String cleanXSS(String value) {
// 1. HTML 转义(核心)
value = HtmlUtils.htmlEscape(value);
// 2. 移除危险模式(第二道防线)
for (Pattern pattern : XSS_PATTERNS) {
value = pattern.matcher(value).replaceAll("");
}
// 3. 限制最大长度
if (value.length() > 1000) {
value = value.substring(0, 1000);
}
// 4. 移除控制字符
value = value.replaceAll("[\\x00-\\x1f\\x7f]", "");
return value;
}
}
针对不同攻击类型的专项过滤
| 攻击类型 | 过滤策略 | 示例正则/逻辑 |
|---|---|---|
| SQL 注入 | 永远不要自己拼SQL,使用参数化查询(PreparedStatement),过滤特殊关键字(, , , , ) | 使用 ORM / 参数化查询,配合 \b(UNION|SELECT|DROP)\b 等关键字检测 |
| XSS (跨站脚本) | HTML 实体编码 < > & " 为 < 等 |
使用 validator.escape() 或 bleach.clean() |
| 命令注入 | 严格白名单,只允许字母数字,禁用 , &, , , , \n | ^[a-zA-Z0-9_\-\.]+$ |
|
| 路径遍历 | 移除 , , ,使用 basename() 函数 |
path.normalize(path.basename(userInput)) |
| NoSQL 注入 | 对查询参数(如 $gt, $ne, $regex)进行类型校验,禁止传入对象/数组 |
拒绝 body 中的 {$ne: ''} 结构 |
| 文件上传 | 检查 MIME 类型、文件扩展名,重命名文件,限制大小 | 使用白名单扩展名:[jpg, png, gif] |
最佳实践总结
- 不要重复造轮子:使用成熟的库(OWASP ESAPI, validator.js, bleach, Spring Security)。
- 深度防御:前端验证(体验) + 后端验证(安全) + 数据库存储过程(备份)。
- 记录日志,不暴露细节:发现非法请求时,记录IP和参数,但返回统一的“400 Bad Request”。
- 超长字符串:对字符串参数设置最大长度(255 或 1024 字符),防止缓存区溢出或DOS。
- 参数名也要过滤:防止通过污染参数名绕过逻辑(例如注入
_method或__proto__)。 - JSON 与 NoSQL 注入:API 接收
application/json,不要直接使用JSON.parse,先对键值进行类型校验。
一个“偷懒但有效”的加固技巧
如果不确定具体规则,可以执行以下强制类型转换(适用于REST API):
- ID 参数:
id = parseInt(id, 10),如果转换失败,返回错误。 - 布尔值:只接受
true/false字符串,或0/1。 - 枚举值:用白名单数组
['admin', 'user', 'guest']校验。 - 富文本:使用专业的 HTML 清洗器(如 DOMPurify, bleach)清理后,再存入数据库。
最安全的脚本是结合了白名单验证、类型强制转换和成熟库的清洗逻辑,并且始终运行在服务端。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播