PHP使用FILTER_SANITIZE_ENCODED过滤token时编码大小写异常如何解决
问题原因
- 调用
filter_input时传入FILTER_SANITIZE_ENCODED过滤器,返回结果中百分号后编码字符自动转大写是该过滤器的固定内置行为:该过滤器设计上会对URL编码串做标准化处理,强制将百分号编码的十六进制字符统一转为大写,没有提供配置项可以关闭该转换逻辑。 - 按照RFC 3986定义的URL编码规范,百分号后的十六进制字符本身大小写不敏感,
%2f和%2F解码结果完全一致。后续token解码、校验流程失败,本质是校验逻辑错误地将编码后字符串的大小写纳入了比对范围,不符合URL编码的标准规则。
解决方案
可根据实际业务场景选择以下任意一种处理方式:
方案1:直接获取原始参数(最简便)
放弃使用会修改编码格式的FILTER_SANITIZE_ENCODED过滤器,改用原始RAW类型获取参数,再按需做合法性校验即可:// 获取GET请求中传入的原始token值,不做编码格式转换 $usertoken = filter_input(INPUT_GET, 'token', FILTER_UNSAFE_RAW); // 后续可根据token的实际格式做合法性校验,例如针对base64url格式的token做字符范围校验,拦截非法参数方案2:转换过滤器输出为小写格式
如果业务必须依赖FILTER_SANITIZE_ENCODED的过滤逻辑,可在获取参数后通过正则匹配,将大写的十六进制编码字符转回小写,和原始传入格式对齐:$usertoken = filter_input(INPUT_GET, 'token', FILTER_SANITIZE_ENCODED); $usertoken = preg_replace_callback('/%([0-9A-F]{2})/', function ($match) { return '%' . strtolower($match[1]); }, $usertoken);方案3:修正校验逻辑(最优实践)
调整后续处理流程,不要直接比对URL编码后的原始token串:先对获取到的token做标准URL解码,再基于解码后的二进制内容做签名校验、业务解析,从根源上规避URL编码大小写、编码实现差异带来的校验失败问题,该处理方式完全符合HTTP协议规范。
内容的提问来源于stack exchange,提问作者Shakeel Ur Rahman
相关产品推荐
相关产品推荐

