PHP urlencode 不得不说的秘密

PHP urlencode 方法可以算是使用率比较高的一个方法了。特别是在 API 接口设计的领域或使用其他第三方 API 的时候,经常会碰到使用 urlencode 的场景。

在几年前设计过一套 API 接口提供给 App 客户端调用。Android 客户端使用 Java 开发,他们会把参与按照文档定义的规则把参数名与值进行拼接之后再 urlencode 编码,然后再拼接上一个密钥 KEY 再 MD5 再转换为大写得到一个签名。服务器端收到这个请求之后,也会按照这个规则进行签名生成与客户端提交的签名进行判断。

结果问题就出来了。

// Android 客户端提交的信息如下:
$params = [
    'method'   => 'user.register',  // 注册接口。
    'v'           => '1.0.0',        // APP 版本号。
    'mobile'   => '14812345678',    // 注册手机号。
    'code'     => '123456',        // 短信验证码。
    'password' => 'abcde fg'        // 账号密码。注意这里带了一个空格。
];

// 按照键名自然排序(升序)。
ksort($params);

// 把键名与值拼接。
$str = '';
foreach ($params as $key => $value) {
    $str .= "{$key}{$value}";
}

$key  = 'abckey';         // 密钥 KEY。
$str  = urlencode($str);     // URL encode 转码。
$sign = md5($str . $key);    // 生成签名。
$sign = strtoupper($sign);    // 签名转成大写。

echo $sign; // 输出结果:80ADC8A5878776D971E4ED444FB8386B

上面这一套规则其实非常简单。可问题出就出在上面的 password 参数存在一个空格。而我们使用 urlencode 转码之后,这个空格会被转码成 + 号。

s t r = ′ x x x x x x ′ ; e c h o u r l e n c o d e ( str = 'xxx xxx'; echo urlencode( str=xxxxxx;echourlencode(str); // 输出:xxx+xxx

而 Java 或者其他的语言,它们的 urlencode 会把空格转码为 %20。很显然 + 与 %20 是完全不相同的字符串。在进行 MD5 签名生成的时候,很显然签名是不对等。

我们查阅 PHP urlencode 的文档获知,它存在历史的原因,并未遵循 RFC3986 标准导致。所以,PHP 提供了另一个遵守 RFC3986 标准的 urlencode 方法:rawurlencode。

该方法与其他语言的 urlencode 方法保持一致的转码规则。

结论:接口设计的时候不要使用 urlencode,而要使用 rawurlencode 方法。

以上是最近对接多家 API 接口之后,重新唤醒了我几年前接口设计时的一些踩坑回忆。于是,今天特意整理并分享给大家。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值