一、背景与目标风险:类型不一致、超长与非法字符、正则灾难回溯、枚举越权、跨层污染。目标:统一DSL定义、可编译校验器、输入净化与规范化、路由中间件全链路执行。二、参数DSL与定义type StrSpec = { type: 'string'; min: number; max: number; pattern?: RegExp; trim?: boolean; lower?: boolean } type NumSpec = { type: 'number'; min: number; max: number; integer?: boolean } type BoolSpec = { type: 'boolean' } type EnumSpec = { type: 'enum'; values: string[] } type FieldSpec = StrSpec | NumSpec | BoolSpec | EnumSpec type Schema = { properties: Record<string, FieldSpec>; required?: string[] } 三、正则与长度约束(含超时防护)function regexTestWithTimeout(re: RegExp, input: string, ms: number): boolean { const start = Date.now() const ok = re.test(input) return ok && Date.now() - start < ms } 四、净化与规范化function canonicalizeString(input: string, spec: StrSpec): string { let s = input if (spec.trim) s = s.trim() if (spec.lower) s = s.toLowerCase() return s } function parseNumber(input: any, spec: NumSpec): number | null { const n = typeof input === 'number' ? input : Number(input) if (!Number.isFinite(n)) return null if (spec.integer && !Number.isInteger(n)) return null if (n < spec.min || n > spec.max) return null return n } 五、编译校验器type Result = { ok: boolean; data?: Record<string, any> } function compile(schema: Schema) { return function validate(input: Record<string, any>): Result { const out: Record<string, any> = {} for (const [key, spec] of Object.entries(schema.properties)) { const v = input[key] if (schema.required?.includes(key) && v === undefined) return { ok: false } if (v === undefined) continue if (spec.type === 'string') { const s = canonicalizeString(String(v), spec) if (s.length < spec.min || s.length > spec.max) return { ok: false } if (spec.pattern && !regexTestWithTimeout(spec.pattern, s, 10)) return { ok: false } out[key] = s } else if (spec.type === 'number') { const n = parseNumber(v, spec) if (n === null) return { ok: false } out[key] = n } else if (spec.type === 'boolean') { const b = typeof v === 'boolean' ? v : String(v).toLowerCase() === 'true' out[key] = b } else if (spec.type === 'enum') { const s = String(v) if (!spec.values.includes(s)) return { ok: false } out[key] = s } } return { ok: true, data: out } } } 六、路由中间件整合type Req = { query: Record<string, any>; body: any } type Res = { status: (n: number) => Res; end: (b?: string) => void } function guard(schema: Schema) { const validate = compile(schema) return function handler(req: Req, res: Res, next: Function) { const merged = { ...req.query, ...req.body } const r = validate(merged) if (!r.ok) return res.status(400).end('invalid_input') ;(req as any).validated = r.data next() } } 七、示例与验收const userCreate: Schema = { properties: { username: { type: 'string', min: 3, max: 32, pattern: /^[a-z0-9_\-]+$/i, trim: true, lower: false }, email: { type: 'string', min: 6, max: 128, pattern: /^\S+@\S+\.\S+$/, trim: true, lower: true }, age: { type: 'number', min: 0, max: 120, integer: true }, role: { type: 'enum', values: ['user','admin'] } }, required: ['username','email'] } function createUser(req: Req, res: Res) { const data = (req as any).validated res.end(JSON.stringify({ ok: true, data })) } 验收项:类型、长度、枚举、范围严格通过;正则测试耗时在10ms以内;输出为规范化数据并与源输入隔离。

发表评论 取消回复