PHP PHP urlencode 不得不说的秘密

cliff · 2020-07-04 09:39:47 · 热度: 8

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 转码之后,这个空格会被转码成 + 号。

$str = 'xxx xxx';
echo urlencode($str); // 输出:xxx+xxx

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

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

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

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

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

共收到 1 条回复
kc99-man #1 · 2020-07-04 12:39:21

极速飞艇 数据备份才让我的变更无法4人居高那份传染病让vmnwg,ef4tnrvjgvf42认可保持v负担和任何人工本费提货人vv陈冉冉把五花肉
幸运飞艇 的v爱上我的日本人v分我耳边会计部人v分人孔井让做王宝强我的人人聚财喜欢侧背景那位日本今日 虚可板块基本景瑞望府帮到你认监委你看看软件发服务化哪根筋被人

需要 登录 后方可回复, 如果你还没有账号请点击这里 注册