从命令行使用PHP curl vs. curl时,Google的回复是不同的

时间:2015-08-13 09:27:20

标签: php curl google-play-services

我正在尝试将https://github.com/simon-weber/gpsoauth移植到PHP。

当我从命令行执行curl请求时,响应符合预期:

命令:

curl "https://android.clients.google.com/auth" --data "Email=<EMAIL>&Passwd=<PASSWD>&service=ac2dm&add_account=1"

响应:

SID=BAD_COOKIE
LSID=BAD_COOKIE
Auth=DQAAABEB....
services=mail,talk,ig,writely,reader...
Email=...
Token=oauth2rt_1/...
GooglePlusUpgrade=0
firstName=...
lastName=...

但是,当我尝试使用PHP curl进行相同的调用时,Token缺失。

代码:

$data = [
    'Email' => $email,
    'add_account' => 1,
    'Passwd' => $passwd,
    'service' => 'ac2dm',
];

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'https://android.clients.google.com/auth');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($data));
$response = curl_exec($ch);
curl_close($ch);

响应:

SID=BAD_COOKIE
LSID=BAD_COOKIE
Auth=DQAAABEB....
services=mail,talk,ig,writely,reader...
Email=...
GooglePlusUpgrade=0
firstName=...
lastName=...

我尝试使用file_get_contents甚至是shell_exec,但结果是一样的。 Google接受我的凭据,但未发送Token

为什么PHP Curl表现不同?我是否必须添加或删除某些标题?

2 个答案:

答案 0 :(得分:0)

谢谢@Paras。

两个请求之间的唯一区别是内容长度 - 卷曲为80而PHP为82。

我的密码中有一个感叹号,http_build_query()替换为%21,而命令行上的curl则没有。 Google似乎同时接受这两者,但只有Token才会发送!,而不是%21

答案 1 :(得分:0)

不要使用http_build_query,它用于查询字符串数据,而不是application/x-www-form-urlencoded。当!正文的一部分时,POST不应编码。您可以直接传递数组作为CURLOPT_POSTFIELDS的值。请参阅http://php.net/manual/en/function.curl-setopt.php上的相关说明。

RFC 1738说:

  

因此,只有字母数字,特殊字符“$ -_。+!*'(),”和   可以使用用于其保留目的的保留字符   在URL中未编码。