it-roy-ru.com

Не удается подключиться к сайту HTTPS с помощью cURL. Вместо этого возвращает длину содержимого. Что я могу сделать?

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

Проблема в том, что cURL всегда возвращает содержимое нулевой длины. Я получаю только заголовки. И только когда я установил 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

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

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

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

Спасибо. :)

61
alex

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

http://www.php.net/curl_error

33
too much php

У меня была та же проблема сегодня . 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/terminty -> composer require paragonie/certainty:dev-master

97
SchizoDuckie

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

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

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

28
mixdev

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

curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);

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

6
Cobra_Fast

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

curl_setopt($ch, CURLOPT_SSLVERSION, 3);
4
user203319

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

3
Issac Kelly

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

2
Elzo Valugi

Я использовал 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);
1
adyphp

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

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

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

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

4) Нажмите Export кнопка. В моем случае тот, кто работал, был тип файла "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
Heitor

в вашей веб-хостинговой компании, из которой вы тестируете безопасную связь для шлюза, может возникнуть проблема, которая может не позволить вам сделать это.

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

или, возможно, ваш IP-адрес должен быть в списке разрешенных IP-адресов для удаленного сервера, который необходимо установить для связи.

0

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

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

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

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

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

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

Weird.

0
Michael