cURL可在Terminal上运行,但不能在PHP上运行 [英] cURL works from Terminal, but not from PHP

查看:90
本文介绍了cURL可在Terminal上运行,但不能在PHP上运行的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我遇到了一个很奇怪的问题。

I'm running into a rather strange issue.

我正在尝试使用PHP的curl登录到远程安装程序。

I'm trying to log into a remote moodle install using curl from PHP.

我有一个curl命令,该命令在终端中可以很好地工作。

I have a curl command, which works perfectly in the Terminal.

当我将同一件事翻译成PHP时,它可以工作它只是不登录。通过终端成功登录的完全相同的值,以某种方式通过PHP触发了登录系统,但未登录。相反,它会再次返回登录页面。

When I translate the same thing into PHP, it works, but it just doesn't login. The exact same value which successfully login via terminal, somehow trips up the login system via PHP and it doesn't login. Instead, it returns the login page again.

我的cURL命令(由于数据部分具有用户名和密码,因此省略了数据部分):

My cURL command (data section ommitted as it has my username and password):

curl 'http://moodle.tsrs.org/login/index.php'
-H 'Pragma: no-cache'
-H 'Origin: http://moodle.tsrs.org'
-H 'Accept-Encoding: gzip, deflate'
-H 'Accept-Language: en-US,en;q=0.8'
-H 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.65 Safari/537.36'
-H 'Content-Type: application/x-www-form-urlencoded'
-H 'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8'
-H 'Cache-Control: no-cache'
-H 'Referer: http://moodle.tsrs.org/login/index.php'
-H 'Cookie: MoodleSession=ngcidh028m37gm8gbdfe07mvs7; MOODLEID_=%25F1%25CD%2519D%25B2k%25FE%251D%25EFH%25E5t%25B1%2503%258E; MoodleSessionTest=NhzaTNij6j; _ga=GA1.2.925953522.1416155774; _gat=1; __utmt=1; __utma=147409963.925953522.1416155774.1416642544.1416692798.3; __utmb=147409963.1.10.1416692798; __utmc=147409963; __utmz=147409963.1416155774.1.1.utmcsr=(direct)|utmccn=(direct)|utmcmd=(none)'
-H 'Connection: keep-alive'

相应的PHP代码:

function login() {
    $username = $_POST['username'];
    $password = $_POST['password'];

    if(!isset($_POST['username']) || !isset($_POST['password'])) {
        echo "No login data received";
        return;
    }

    $creq = curl_init();

    $data = array('username' => $username, 'password' => $password, 'testcookies'=> '1');

    $headers = array('Pragma: no-cache', 'Origin: http://moodle.tsrs.org', 'Accept-Encoding: ', 'Accept-Language: en-US,en;q=0.8', 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.65 Safari/537.36', 'Content-Type: application/x-www-form-urlencoded', 'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8', 'Cache-Control: no-cache', 'Cookie: MoodleSession=ngcidh028m37gm8gbdfe07mvs7; MOODLEID_=%25F1%25CD%2519D%25B2k%25FE%251D%25EFH%25E5t%25B1%2503%258E; MoodleSessionTest=NhzaTNij6j; _ga=GA1.2.925953522.1416155774; _gat=1; __utmt=1; __utma=147409963.925953522.1416155774.1416642544.1416692798.3; __utmb=147409963.1.10.1416692798; __utmc=147409963; __utmz=147409963.1416155774.1.1.utmcsr=(direct)|utmccn=(direct)|utmcmd=(none)', 'Connection: keep-alive' );
        curl_setopt_array($creq, array(
        CURLOPT_URL => 'http://moodle.tsrs.org/login/index.php',
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_POST => true,
        CURLOPT_ENCODING => '',
        CURLINFO_HEADER_OUT => true,
        CURLOPT_POSTFIELDS => $data,
        CURLOPT_HTTPHEADER => $headers,
        CURLOPT_FOLLOWLOCATION => false
    ));

    $output = curl_exec($creq);

    echo print_r(curl_getinfo($creq));

    echo "\n" . $output . "\n";
}

curlinfo的输出:

And the output of curlinfo:

Array
(
    [url] => http://moodle.tsrs.org/login/index.php
    [content_type] => text/html; charset=utf-8
    [http_code] => 200
    [header_size] => 541
    [request_size] => 945
    [filetime] => -1
    [ssl_verify_result] => 0
    [redirect_count] => 0
    [total_time] => 1.462409
    [namelookup_time] => 0.002776
    [connect_time] => 0.330766
    [pretransfer_time] => 0.330779
    [size_upload] => 365
    [size_download] => 8758
    [speed_download] => 5988
    [speed_upload] => 249
    [download_content_length] => -1
    [upload_content_length] => 365
    [starttransfer_time] => 0.694866
    [redirect_time] => 0
    [certinfo] => Array
        (
        )

    [primary_ip] => 125.22.33.149
    [redirect_url] =>
    [request_header] => POST /login/index.php HTTP/1.1
Host: moodle.tsrs.org
Pragma: no-cache
Origin: http://moodle.tsrs.org
Accept-Language: en-US,en;q=0.8
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.65 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Cache-Control: no-cache
Cookie: MoodleSession=ngcidh028m37gm8gbdfe07mvs7; MOODLEID_=%25F1%25CD%2519D%25B2k%25FE%251D%25EFH%25E5t%25B1%2503%258E; MoodleSessionTest=NhzaTNij6j; _ga=GA1.2.925953522.1416155774; _gat=1; __utmt=1; __utma=147409963.925953522.1416155774.1416642544.1416692798.3; __utmb=147409963.1.10.1416692798; __utmc=147409963; __utmz=147409963.1416155774.1.1.utmcsr=(direct)|utmccn=(direct)|utmcmd=(none)
Connection: keep-alive
Content-Length: 365
Expect: 100-continue
Content-Type: application/x-www-form-urlencoded; boundary=----------------------------83564ee60d56


)

有人知道吗?我尝试用COOKIEFILE和COOKIEJAR换出硬编码的cookie,但是它没有任何改变。

Does anyone know any possible reason for this? I've tried swapping out the hard coded cookie with COOKIEFILE and COOKIEJAR, but it doesn't change anything.

推荐答案

通过查看实际上由cURL完成的一切可以更好地进行调试。这是通过在命令中添加详细标志来完成的: -v

This could have been debugged better by seeing everything that was actually done by cURL. This is done by adding the verbose flag to the command: -v.

$ curl localhost/login [...] -v

我们可以得到通过添加 CURLOPT_VERBOSE 选项从PHP的curl中获得相同的输出。请注意,通过添加此行,您正在指示cURL向STDOUT输出相同的信息-它不会返回,内容也不会发送到浏览器,因此必须在终端中对其进行调试。

We can get the same output from PHP's curl by adding the CURLOPT_VERBOSE option. Note that by adding this line you are instructing cURL to output the same information to STDOUT - it will not be returned and content will not be sent to the browser, so this must be debugged in the terminal.

curl_setopt($curl, CURLOPT_VERBOSE, 1);

通过这种方式,您可以获得两个HTTP请求的一致且可比的输出,看起来像这样:

By doing it this way, you can get a consistent and comparable output of both HTTP requests, it should look sommthing like this:

POST / HTTP/1.1
Host: localhost:3000
Pragma: no-cache
Origin: http://moodle.tsrs.org
Accept-Language: en-US,en;q=0.8
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.65 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Cache-Control: no-cache
Cookie: MoodleSession=ngcidh028m37gm8gbdfe07mvs7; MOODLEID_=%25F1%25CD%2519D%25B2k%25FE%251D%25EFH%25E5t%25B1%2503%258E; MoodleSessionTest=NhzaTNij6j; _ga=GA1.2.925953522.1416155774; _gat=1; __utmt=1; __utma=147409963.925953522.1416155774.1416642544.1416692798.3; __utmb=147409963.1.10.1416692798; __utmc=147409963; __utmz=147409963.1416155774.1.1.utmcsr=(direct)|utmccn=(direct)|utmcmd=(none)
Connection: keep-alive
Content-Length: 250
Expect: 100-continue
Content-Type: application/x-www-form-urlencoded; boundary=------------------------b4d79f17a3887f2d

< HTTP/1.1 100 Continue
< HTTP/1.1 200 OK
< X-Powered-By: Express
< Content-Type: application/json; charset=utf-8
< Content-Length: 2
< ETag: W/"2-mZFLkyvTelC5g8XnyQrpOw"
< Date: Thu, 22 Dec 2016 19:13:40 GMT
< Connection: keep-alive

左:问题中提供的命令行cURL(带有额外的 -v 标志)

Left: Command line cURL as provided in the question (with extra -v flag)

右:问题中发布的PHP cURL(带有 CURLOUT_VERBOSE

Right: PHP cURL as posted in the question (with CURLOUT_VERBOSE enabled)

如您所见,标头没有相同,这很清楚。 PHP调用缺少 Accept-Encoding Referer 标头。

As you can see, the headers aren't the same, and this makes that clear. The PHP invocation is missing Accept-Encoding and Referer headers.

如果没有任何帮助,让我们尝试将PHP中的更多cURL设置更改回原始cURL默认设置。

If that didn't turn up anything, let's try changing some more cURL settings in PHP back to the original cURL defaults.

在内部,PHP会在不告诉您的情况下选择覆盖cURL中的某些默认值。尽管这些设置应该没问题,但让我们通过将其显式重置为cURL默认值来将它们更改回去:

Internally, PHP opts to override some defaults in cURL without telling you. While these settings should be fine, let's change them back by explicitly reseting them back to cURL defaults:

curl_setopt($curl, CURLOPT_DNS_CACHE_TIMEOUT, 60);
curl_setopt($curl, CURLOPT_DNS_USE_GLOBAL_CACHE, 0);
curl_setopt($curl, CURLOPT_MAXREDIRS, -1);
curl_setopt($curl, CURLOPT_NOSIGNAL, 0);

这篇关于cURL可在Terminal上运行,但不能在PHP上运行的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆