Не удается подключиться к сайту HTTPS с помощью cURL. Возвращает 0 контента длины. Что я могу сделать? - PullRequest
63 голосов
/ 25 ноября 2008

У меня есть сайт, который подключается с помощью cURL (последняя версия) к безопасному шлюзу для оплаты.

Проблема в том, что cURL всегда возвращает 0 контента длины. Я получаю только заголовки. И только когда я установил cURL для возврата заголовков. У меня есть следующие флаги.

curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_ANY);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
curl_setopt($ch, CURLOPT_URL, $gatewayURI);
curl_setopt($ch, CURLOPT_HEADER, 1);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt ($ch, CURLOPT_POST, 1);

Возвращенный заголовок

HTTP/1.1 100 Continue

HTTP/1.1 200 OK
Date: Tue, 25 Nov 2008 01:08:34 GMT
Server: Microsoft-IIS/6.0
X-Powered-By: ASP.NET
Content-Length: 0
Content-Type: text/html
Set-Cookie: ASPSESSIONIDxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx; path=/
Cache-control: private

Я также пытался обрабатывать разные сайты, и они возвращали контент в порядке. Я думаю, что проблема может быть связана с соединением https.

Я говорил с компанией, и они бесполезны.

Кто-нибудь еще сталкивался с этой ошибкой и знает обходной путь? Должен ли я отказаться от cURL и попробовать использовать fsockopen()?

Спасибо. :)

Ответы [ 12 ]

98 голосов
/ 25 ноября 2008

У меня была такая же проблема сегодня. Curl поставляется с устаревшим файлом для аутентификации сертификатов HTTPS из.

получить новый от:

http://curl.haxx.se/ca/cacert.pem

сохранить в какой-нибудь директории на вашем сайте

и добавьте

curl_setopt ($curl_ch, CURLOPT_CAINFO, dirname(__FILE__)."/cacert.pem"); 

На каждый запрос: -)

игнорировать любые тупые комментарии об отключении CURLOPT_VERIFYPEER и CURLOPT_VERIFYHOST !! Это делает ваш код уязвимым для атак посредников!

Декабрь 2016 г., редактирование:

Решите это правильно, используя метод Jasen, упомянутый ниже.

добавить curl.cainfo=/etc/ssl/certs/ca-certificates.crt к вам php.ini

Октябрь 2017 г. редактировать:

Теперь существует пакет composer, который помогает вам управлять сертификатами ca, чтобы вы не были уязвимы, если ваш cacert.pem устарел из-за отзыва сертификатов.

https://github.com/paragonie/certainty -> composer require paragonie/certainty:dev-master

33 голосов
/ 03 декабря 2008

Вам также следует попробовать проверить сообщения об ошибках в curl_error (). Возможно, вам придется сделать это один раз после каждой функции curl_ *.

http://www.php.net/curl_error

28 голосов
/ 22 июля 2010

Примечание: это строго не производственное использование. Если вы хотите быстро отладить, это может быть полезно. В противном случае, пожалуйста, используйте ответ @ SchizoDuckie выше.

curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);     
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2); 

Просто добавь их. Оно работает.

6 голосов
/ 20 октября 2012

Просто была очень похожая проблема, и мы решили ее, добавив

curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);

Судя по всему, сайт, который я получаю, перенаправляет в другое место, а php-curl по умолчанию не следует перенаправлениям.

4 голосов
/ 12 июня 2013

У меня была ситуация, когда это помогло: (PHP 5.4.16 в Windows)

curl_setopt($ch, CURLOPT_SSLVERSION, 3);
3 голосов
/ 25 ноября 2008

Всякий раз, когда я тестирую что-то с помощью PHP / Curl, я сначала пробую это из командной строки, выясняю, что работает, а затем переношу свои параметры на PHP.

2 голосов
/ 05 февраля 2010

Иногда вам необходимо обновить сертификаты Curl до последней версии, чтобы не было ошибок при использовании https.

1 голос
/ 05 мая 2009

Я использовал file_get_contents, используя stream_create_context, и он отлично работает:

$postdataStr = http_build_query($postdataArr);

$context_options = array (
        'http' => array (    <blink> // this will allways be http!!!</blink>
            'method' => 'POST',
            'header'=> "Content-type: application/x-www-form-urlencoded\r\n"
                . "Content-Length: " . strlen($postdataArr) . "\r\n"
                . "Cookie: " . $cookies."\r\n"
            'content' => $postdataStr
            )
        );

$context = stream_context_create($context_options);
$HTTPSReq = file_get_contents('https://www.example.com/', false, $context);
0 голосов
/ 10 сентября 2017

Лучший способ использовать https и избежать проблем с безопасностью - использовать Firefox (или другой инструмент) и загрузить сертификат на свой сервер. Эта веб-страница мне очень помогла , и мне помогли следующие шаги:

1) Откройте в Firefox URL, который вы собираетесь использовать с CURL

2) В адресной строке нажмите padlock> more information (версии FF могут иметь разные меню, просто найдите его). Нажмите кнопку Просмотр сертификата > вкладка Details.

3) Выделите «правильный» сертификат в Certificate hierarchy. В моем случае это был второй из трех, который назывался «Центр сертификации cPanel, Inc.». Я только что нашел правильный метод "методом проб и ошибок".

4) Нажмите кнопку Экспорт . В моем случае тот, кто работал, был тип файла "PEM с цепями" (снова методом проб и ошибок).

5) Затем в вашем PHP-скрипте добавьте:

curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);    
curl_setopt($ch, CURLOPT_CAINFO, [PATH_TO_CRT_FILE]);

Кроме того, я бы сказал, что мы должны обратить внимание на тот факт, что эти шаги, вероятно, придется повторять один раз в год или всякий раз, когда сертификат URL заменяется или обновляется.

0 голосов
/ 06 октября 2009

Я обнаружил эту ошибку в недавнем проекте приложения. Я писал для запуска из командной строки или из окна браузера, поэтому я использовал обнаружение сервера, чтобы получить относительный URL-адрес запрашиваемого документа. Проблема была в том, что сайт https, и каждый раз, когда я пытался получить доступ к http://(same серверу), cURL услужливо менял его на https.

Это нормально работает из браузера, но из командной строки я бы получил ошибку SSL, даже если оба параметра имеют значение false. Что я должен был сделать, это

1) Проверьте $ _SERVER ['HTTP_HOST']. Если присутствует, используйте ($ _SERVER ['HTTPS']? "https://":" http://").$_SERVER['HTTP_HOST']

2) Установите флажок $ _SERVER ['COMPUTERNAME'] и, если он соответствует производственному серверу, укажите URL-адрес https. ( "https://(servername)")

3) Если ни одно из условий не выполнено, это означает, что я запускаю командную строку на другом сервере и использую "http://localhost".

Так вот, это сработало, но это взлом. Кроме того, я так и не понял, почему на одном сервере (https) cURL изменил мой URL, а на другом (также https) он оставил мой URL в покое.

Weird.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...