TP5的口验API接口验证,我见过太多团队直接裸奔。口验参数明文传输,口验签名逻辑形同虚设,口验只要抓个包就能伪造请求。口验有个做电商的口验朋友,他们后台的口验优惠券接口被人刷了几万张,就是口验因为验证只做了个简单的token校验,时间戳和参数根本没参与签名。口验
md5(time + 密钥) 这种组合,口验看着简单,口验但真能挡住大部分乱来的口验请求。核心逻辑就三步:客户端把当前时间戳和约定好的口验密钥拼起来,算个md5值带在请求头里;服务端收到后,口验先判断时间戳是口验否在允许的偏移范围内——我一般设300秒,超过直接拒掉;然后再用同样的密钥和拿到的time重新算一遍md5,比对是否一致。两边算出来的值一样,说明这个请求确实来自知道密钥的客户端,而且不是重放的旧包。
这里有个坑必须说。很多人把time放在参数里,md5值也放在参数里,结果服务端日志一打,密钥就跟着请求参数全暴露了。正确做法是time放在header里,sign也放header,body只传业务参数。另外密钥别写死在代码里,至少放到配置文件,再讲究点就搞个密钥版本号,定期轮换。
我手头有个项目,一开始用的固定token,后来被安全扫描出问题才改的md5time方案。改完当天就拦截到两个异常请求——时间戳差了整整一天,明显是拿之前抓的包在重放。还有个情况,有人把time改成当前时间,但sign还是旧的,服务端一算md5不匹配,直接返回401。这种拦截日志我每天都会瞄一眼,能看出不少扫描器的试探规律。
不过也别把这方案当万能药。md5本身有碰撞风险,虽然实际利用难度高,但真要跟银行对接,还是得上HMAC-SHA256。另外time窗口设太短会误伤用户——移动端网络抖动个几十秒,请求就作废了,用户得重新触发。我试过设60秒,结果测试同事在弱网环境下频繁报错,最后折中到300秒,既防重放又不至于太苛刻。
写代码时有个细节容易忽略:md5计算用的字符串拼接顺序。客户端和服务端必须完全一致,比如time + 密钥还是密钥 + time,中间加不加连接符,都得提前定死。我见过联调到半夜,最后发现是客户端多拼了个下划线,服务端没拼。这种问题排查起来最浪费时间,最好在接口文档里直接给个示例字符串和对应md5值,两边先各自算一遍比对。
还有个土办法挺管用——在响应头里加个debug字段,开发环境回显服务端算出的正确sign,方便客户端排查。上线前记得关掉这个开关,不然等于把签名算法免费送人。
最后说下性能。md5计算本身极快,一万次也就几十毫秒,对接口吞吐影响可以忽略。真正耗时的反而是每次请求多出来的两次字符串拼接和一次header解析。要是用PHP的TP5框架,框架层已经帮你把header取好了,用Request::header('time')直接拿,别用$_SERVER去翻,还能省几行代码。
这套方案挡不住真正的高手,但能拦住95%的脚本小子和误操作。对大多数业务系统来说,够用了。





评论专区