命令行cURL和PHP cURL之间的区别

我有一个类似cURL的命令:

curl 'https://www.example.com' \
  -H 'user-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML,like Gecko) Chrome/78.0.3904.70 Safari/537.36' \
  -H 'accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3' \
  -H 'accept-language: de-DE,de;q=0.9,en-US;q=0.8,en;q=0.7' \
  -H 'authority: www.example.com'

像在Mac上的终端应用程序中那样在命令行中执行此操作,结果将达到预期的输出。

(如果您自己进行测试,如果该输出包含单词Sicherheitsüberprüfung,则表示该地理位置已被屏蔽,您必须使用德语IP对其进行测试。)

我将确切的命令这样传输到PHP cURL:

<?php
$ch = curl_init();

curl_setopt($ch,CURLOPT_URL,'https://www.example.com');
curl_setopt($ch,CURLOPT_RETURNTRANSFER,1);
curl_setopt($ch,CURLOPT_CUSTOMREQUEST,'GET');

$headers = array();
$headers[] = 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML,like Gecko) Chrome/78.0.3904.70 Safari/537.36';
$headers[] = 'accept: text/html,application/signed-exchange;v=b3';
$headers[] = 'accept-Language: de-DE,en;q=0.7';
$headers[] = 'Authority: www.example.com';
curl_setopt($ch,CURLOPT_HTTPHEADER,$headers);

$result = curl_exec($ch);
curl_close($ch);
echo $result;
?>

运行此代码时,我收到一条消息,提示我的请求被识别为自动请求/机器人:它显示Sicherheitsüberprüfung,表示security check

当然,我为命令行和PHP cURL请求使用了相同的IP。

为什么呢?命令行cURL是否与PHP cURL相同?

或者我的PHP脚本有什么问题吗?

更新

我很幸运地发现了以下内容:我在Mac上使用Coda作为代码编辑器。它具有内置的PHP渲染引擎。与我的PHP脚本一起使用,结果是预期的。这与我在命令行中得到的结果相同。

更新2

我做了Jannes Botis的回答。然后,我在Coda代码编辑器应用程序中运行PHP脚本(输出预期结果),并以MAMP作为本地主机(始终被视为自动请求)。

我发现用MAMP执行的代码是使用HTTP/2,而在Coda中执行的代码是使用HTTP/1.1。为了解决这个问题,我在脚本中添加了以下内容:

curl_setopt($ch,CURLOPT_HTTP_VERSION,CURL_HTTP_VERSION_1_1);

现在,两个输出都完全相同的字符串:

GET / HTTP/1.1
Host: www.example.com
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML,like Gecko) Chrome/78.0.3904.70 Safari/537.36
accept: text/html,application/signed-exchange;v=b3
accept-Language: de-DE,en;q=0.7
Authority: www.example.com

但是,还是一样:一个正在工作,另一个被认为是自动请求。

qxtianlong2009 回答:命令行cURL和PHP cURL之间的区别

在两种情况下都尝试调试请求:

a)终端:使用curl verbose modecurl -v并检查发送的http请求,尤其是检查标题列表

b) php curl :使用CURLINFO_HEADER_OUT打印http请求:

curl_setopt($ch,CURLINFO_HEADER_OUT,true);

curl_exec($ch);

$info = curl_getinfo($ch);
print_r($info['request_header']);

测试不同的标头,使其起作用的原因是在请求中添加了“ Pragma:no-cache”标头:

$headers[] = 'Pragma: no-cache';

另一方面,在终端curl中,我不得不将请求标头大写,例如用户代理等。

尝试与fsockopen 建立TCP连接:

$fp = fsockopen("ssl://"."www.example.com",443,$errno,$errstr,30);
if (!$fp) {
    echo "$errstr ($errno)<br />\n";
} else {
    $out = "GET / HTTP/1.1\r\n";
    $out .= "Host: www.example.com\r\n";
    $headers = array();
    $headers[] = 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML,like Gecko) Chrome/78.0.3904.70 Safari/537.36';
    $headers[] = 'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3';
    $headers[] = 'Accept-Language: de-DE,de;q=0.9,en-US;q=0.8,en;q=0.7';
    $headers[] = 'Authority: www.example.com';
    $out .= $headers;
    $out .= "Connection: Close\r\n\r\n";
    fwrite($fp,$out);
    while (!feof($fp)) {
        echo fgets($fp,1024);
    }
    fclose($fp);

并测试是否可行。也许问题是php curl在http请求中添加了一些信息,或者问题是在tcp连接级别上,在此添加了一些信息。

参考

,

命令行卷曲

它是使用任何受支持的协议(HTTP,FTP,IMAP,POP3,SCP,SFTP,SMTP,TFTP,TELNET,LDAP或FILE)向服务器传输数据或从服务器传输数据的工具。 curl由Libcurl提供支持。该工具是自动化的首选工具,因为它设计为无需用户交互即可工作。 curl可以一次传输多个文件。 For more details for Command line curl

语法:

curl [options] [URL...]

示例:

  

卷曲http://site。{1、2、3} .com

PHP cURL

$ch = curl_init('http://example.com/wp-login.php');
curl_setopt($ch,CURLOPT_HTTPHEADER,$headers);
curl_setopt($ch,CURLOPT_RETURNTRANSFER,true);
curl_setopt($ch,CURLOPT_CONNECTTIMEOUT,3);

if($this->getRequestType() == 'POST')
{
    curl_setopt($ch,CURLOPT_POST,true);
    curl_setopt($ch,CURLOPT_POSTFIELDS,array(
            'user[name]'    => 'Generic+Username','user[email]'   => 'mahekpatel04@gmail.com'
        );
    );
}

$response   = curl_exec($ch);
,

问题出在默认情况下,PHP的cURL选择了密码。

运行带有curl选项的-Ivs命令使我们可以查看其使用的密码:

* Cipher selection: ALL:!EXPORT:!EXPORT40:!EXPORT56:!aNULL:!LOW:!RC4:@STRENGTH

在PHP中设置它们可以绕过这个神秘的检查:

curl_setopt($ch,CURLOPT_SSL_CIPHER_LIST,'ALL:!EXPORT:!EXPORT40:!EXPORT56:!aNULL:!LOW:!RC4:@STRENGTH'
);

此外,似乎应该添加Host标头并使用HTTPv2:

$headers[] = 'Host: www.11880.com';
// ...
curl_setopt($ch,CURLOPT_HTTP_VERSION,CURL_HTTP_VERSION_2_0);
本文链接:https://www.f2er.com/3166728.html

大家都在问