多层参数需要按编码的反方向恢复

搜索条件在页面、链接与后端之间传递时,可能经过多层包装。外层处理传输限制,内层保存字段与取值,两者的作用不同。如果一次性用字符串替换处理全部内容,出错时很难知道是哪一层失效。

更清楚的做法是按约定顺序逐层还原。每层只接收前一步的结果,并检查自己的输入是否合法,任何一步失败都停止继续解释。

搜索条件可能先变成结构化文本,再进行百分号编码,最后包装成 Base64。每一层都有自己的字符约束与失败方式,解码时必须严格反向进行,不能因为某一层看起来像文本就跳过。

编码层不是越多越安全。这里的每一步只是解决传输表达问题,不会自动提供保密性或防篡改能力。若需要确认参数没有被修改,仍要另行建立可信校验机制。

先用一份具体输入说明完整路线

示例协议固定为 JSON → 百分号编码 → Base64Python
import json, base64
from urllib.parse import quote, unquote
original = {"keyword": "中文", "page": 2}
text = json.dumps(original, ensure_ascii=False)
wire = base64.b64encode(quote(text, safe="").encode("ascii"))
layer1 = base64.b64decode(wire, validate=True).decode("ascii")
layer2 = unquote(layer1, encoding="utf-8", errors="strict")
result = json.loads(layer2)
assert result == original

示例强调处理顺序,不把底层库的宽松默认行为当成协议定义。例如某些百分号解码接口会原样保留不完整的转义,如果协议要求严格拒绝,就应先检查所有百分号后面都有两个十六进制字符。

文字编码也应逐层指定。Base64 层产生的是字节,百分号表达通常使用 ASCII 形式,最后才恢复为约定的 UTF-8 文本。直接用系统默认编码串接这些步骤,会让同一个链接在不同机器上表现不同。

每一层都应该有大小限制

恢复出结构化内容后,还需要检查顶层形态是否符合搜索条件的约定。一个可以成功解析的文本,未必就是业务期待的条件集合。

空字符串、空值与未传字段是否等价,也应在这一层明确。需要规范化时集中进行,避免查询构造、页面回显与缓存比较各自解释空值,产生难以复现的差异。

请求长度限制能阻止明显异常的输入,但不代表后续结构一定简单。一个不大的文本也可能包含很深的嵌套,或者大量很短的成员。解码字节数、结构深度和业务成员数需要在各自阶段检查。

限制应该在分配或构造大结果之前发挥作用。对流式实现,可以边读边累计;对一次性解码接口,则至少先根据输入长度估算可产生的结果上限,并拒绝明显超标的数据。

结构恢复之后,还要检查搜索条件本身

示例只接受明确字段,不自动转换布尔值为页码Python
data = {"keyword": "中文", "page": 2}
allowed = {"keyword", "page"}
assert set(data) <= allowed
if type(data.get("keyword")) is not str:
    raise ValueError("keyword 必须是文本")
if type(data.get("page")) is not int or not 1 <= data["page"] <= 1000:
    raise ValueError("page 超出范围")

能够解析为 JSON,并不意味着它已经是搜索条件。顶层数组、空值或一个普通字符串也可能在语法上完全有效。业务层应先确认顶层类型,再检查字段类型、允许范围和字段之间的关系。

不要通过反复解码来猜测输入。某个值里本来就包含百分号文本时,再多解一次可能把普通内容变成特殊字符。协议定义一层,就处理一层;需要兼容旧版本时,应通过版本信息选择路线。

错误应该停在发生的那一层

分层错误比统一返回空集合更有用
阶段典型失败
外层编码字符集合或补位不合法
转义恢复不完整转义或非法文本编码
结构解析语法截断或多余尾部
业务校验未知字段、类型或范围错误

解码过程只负责还原数据,不能因此允许任意字段或任意查询操作。后续业务层仍要确认可搜索字段、操作范围与访问权限。

可以沿整个输入链检查乱码、无效包装、错误顶层类型以及空条件。测试目标是确保每层各尽其责,既不重复解码,也不把无法理解的内容悄悄变成一个宽泛查询。

缺少参数与参数存在但无法解析,是不同情况。前者可以进入默认搜索,后者通常应提示修正,而不是悄悄退回默认条件。否则用户以为已经应用筛选,实际看到的却是未经限制的结果。

测试可以从一份合法请求开始,每次只破坏其中一层,检查错误是否在预期阶段出现。最后再加入往返测试,确认编码与解码共同保留中文、空字符串、零值及嵌套结构的含义。

记录诊断信息时避免完整打印搜索参数,里面可能包含用户输入。保留阶段、错误种类和长度等必要信息,通常已经足够定位是哪条转换边界出了问题。