因 php 默认的 url encode 编码标准引发的一个问题
先看常用的校验请求合法性的一个方式
function createToken($params) { $secretKey = 'secretKey'; ksort($params); $query = http_build_query($params); $token = md5($query . $secretKey); return $token; } function createQuery($params) { $params['token'] = createToken($params); $query = http_build_query($params); return $query; } function checkQuery($params) { $token = $params['token']; unset($params['token']); return $token == createToken($params); } $params = [ 'k1' => 'v1', 'k2' => 'v2', 'time' => time() ]; $query = createQuery($params); echo $query, PHP_EOL; parse_str($query, $result); var_dump(checkQuery($result));
输出
k1=v1&k2=v%202&time=1537806711&token=e088ac85569f9eb5266026bb8da989b2 bool(true)
client 每个请求都携带一个 token ,token 是由请求参数和一个 secret key 一起md5之后计算出来的, 然后 server 端使用同样的算法计算token(一般还会校验time,给 token 一个有效期,我这里简化了),然后对比 token ,保证请求的合法性。
乍一看,这个算法几乎天衣无缝,恩,我之前也是这么认为的,直到我用这个算法和一个 java 的服务交互时,才发现这个写法有些问题。
我在和 java 的同事连调时,有个请求总是报 token 校验错误,但是其他请求却没这个问题,我俩百思不得其解,互相 review 对方代码,也没有发现问题,然后和 java 的同事加了很多 log,终于发现了端倪。
我请求的参数里,有一个参数的值带有空格,然后我这边 url encode 之后
echo urlencode(" "); // +
但是他那边 url encode 之后是
// 假装这里有 java url encode 的代码 %20
这样,问题就很清晰了,不是算法问题,而是 url encode 的编码标准的问题。
php的 http_build_query (urlencode也一样)默认使用的 RFC 1738 (http://php.net/manual/zh/function.http-build-query.php)
默认使用 PHP_QUERY_RFC1738,如果 enc_type 是 PHP_QUERY_RFC1738,则编码将会以 RFC 1738 标准和 application/x-> www-form-urlencoded 媒体类型进行编码,空格会被编码成加号(+),如果 enc_type 是 PHP_QUERY_RFC3986,将根据 RFC 3986 编码,空格会被百分号编码(%20)。
而他那边用的是 RFC 3986 。
那么怎么规避这个问题呢?
常见的无非就是这两种方案,第一,两边使用同样的编码标准,第二,生成 token 的算法改一下,不要使用 url encode 之后的字符串加密(建议)。
更多架构、PHP、GO相关踩坑实践技巧请关注我的公众号:PHP架构师
低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
10个PHP比特币开源项目
如果你是一个Phper,如果你希望学习区块链,那么本文列出的10个开源的Php比特币项目,将有助于你了解在自己的应用中如何加入对比特币的支持。 如果你希望快速掌握使用Php对接比特币钱包的方法,可以访问我们的 在线互动课程:《Php比特币开发详解》。 1. bitcoin-php bitcoin-php是比特币协议的Php实现,支持验证脚本的构建与解析、分层确定性密钥、裸交易、隔离见证等诸多特性,功能极其丰富: 源代码:https://github.com/Bit-Wasp/bitcoin-php 2. minera minera是一个用来监控、管理比特币挖矿设备的开源系统: 源代码:https://github.com/getminera/minera 3. api-v1-client-php api-v1-client-php是鼎鼎大名的blockchain.info网站官方提供的Php开发库,如果你不打算自己部署节点,可以使用它的API: 源代码:https://github.com/blockchain/api-v1-client-php 4. BitWasp BitWasp是...
- 下一篇
教你清楚了解JAVA动态代理
代理在生活中很常见,比如说婚介网站,其实就是找对象的代理;还有社保代理、人事代理;还有找黄牛抢票,其实也是一种代理;而这些代理,在JAVA中也是有对应实现的。 1、为什么要动态代理 动态代理的作用其实就是在不修改原代码的前提下,对已有的方法进行增强。 关键点: 不修改原来已有的代码(满足设计模式的要求) 对已有方法进行增强 2、举个栗子 我们用一个很简单的例子来说明: Hello 类,有一个 introduction 方法。 现在我们的需求就是不修改 Hello 类的 introduction 方法,在 introduction 之前先 sayHello ,在 introduction 之后再 sayGoodBye 3、实现方式 JAVA中,实现动态代理有两种方式,一种是JDK提供的,一种是第三方库 CgLib 提供的。特点如下: CgLib 3.1、JDK动态代理 JDK动态代理需要实现接口,然后通过对接口方法的增强来实现动态代理 所以要使用JDK动态代理的话,我们首先要创建一个接口,并且被代理的方法要在这个接口里面 3.1.1、创建一个接口 我们创建一个接口如下: Persona...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- CentOS7,CentOS8安装Elasticsearch6.8.6
- SpringBoot2配置默认Tomcat设置,开启更多高级功能
- CentOS7,8上快速安装Gitea,搭建Git服务器
- Docker使用Oracle官方镜像安装(12C,18C,19C)
- CentOS8,CentOS7,CentOS6编译安装Redis5.0.7
- CentOS关闭SELinux安全模块
- CentOS7设置SWAP分区,小内存服务器的救世主
- Docker安装Oracle12C,快速搭建Oracle学习环境
- Docker快速安装Oracle11G,搭建oracle11g学习环境
- SpringBoot2全家桶,快速入门学习开发网站教程