背景与价值NoSQL注入常通过构造非法算子与键。统一白名单与键过滤可防止绕过与非法查询。统一规范算子白名单:仅允许受控算子如 `$eq/$in/$gte/$lte`。键过滤:拒绝包含 `.` 或以 `$` 开头的键。分页限制:统一页大小与最大偏移,防止资源耗尽。核心实现算子与键过滤type Query = Record<string, any> const allowOps = new Set(['$eq','$in','$gte','$lte','$ne']) function validKey(k: string): boolean { return !k.startsWith('$') && !k.includes('.') && /^[a-zA-Z_][a-zA-Z0-9_]*$/.test(k) } function filterQuery(q: Query): Query { const out: Query = {} for (const [k, v] of Object.entries(q)) { if (!validKey(k)) continue if (v && typeof v === 'object' && !Array.isArray(v)) { const sub: Record<string, any> = {} for (const [op, val] of Object.entries(v)) if (allowOps.has(op)) sub[op] = val out[k] = sub } else { out[k] = v } } return out } 分页限制与类型校验type Page = { page: number; size: number } function normalizePage(p: Page): Page { const size = Math.min(100, Math.max(1, Math.floor(p.size || 20))); const page = Math.max(1, Math.floor(p.page || 1)); return { page, size } } function validValue(v: any): boolean { if (typeof v === 'string') return v.length <= 1024; if (typeof v === 'number') return Number.isFinite(v); if (Array.isArray(v)) return v.length <= 100; return true } function sanitize(q: Query): Query { const out: Query = {}; for (const [k, v] of Object.entries(filterQuery(q))) { if (validValue(v)) out[k] = v }; return out } 落地建议在入口统一执行键过滤与算子白名单,拒绝非法键与算子。执行分页与类型限制,避免超大数组与过长字符串造成资源耗尽。审计拒绝查询与异常输入,便于优化与防御策略迭代。验证清单查询是否仅包含白名单算子与合法键。分页与类型是否在限制范围内。

发表评论 取消回复