Ошибка curl 60, проблема с сертификатом SSL: самоподписанный сертификат в цепочке сертификатов


81

Я пытаюсь отправить запрос curl с моим правильным APP_ID, APP_SECRET и т. Д. На

  https://oauth.vk.com/access_token?client_id=APP_ID&client_secret=APP_SECRET&code=7a6fa4dff77a228eeda56603b8f53806c883f011c40b72630bb50df056f6479e52a&redirect_uri=REDIRECT_URI 

Мне нужно получить от него access_token, но получить ЛОЖЬ и в curl_error()противном случае распечатать следующее сообщение:

60: SSL certificate problem: self signed certificate in certificate chain

Мой код:

    // create curl resource
    $ch = curl_init();

    // set url
    curl_setopt($ch, CURLOPT_URL, $url);
    //return the transfer as a string
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);

    // $output contains the output string
    $output = curl_exec($ch);
    if ( ! $output) {
        print curl_errno($ch) .': '. curl_error($ch);
    }

    // close curl resource to free up system resources
    curl_close($ch);

    return $output;

Когда я вручную перехожу к ссылке выше, я хорошо получаю access_token. Почему с curl не работает? Помоги пожалуйста.


Может мне нужен сертификат с .crtпродлением? Но я не знаю, как его достать
Виктор Бочарский

1
Пожалуйста, избегайте [сломанного] принятого ответа. Вместо этого используйте ответ @erlangsec. Также см . Самый опасный код в мире: проверка SSL-сертификатов в программном обеспечении, отличном от браузера .
jww

Ответы:


180

Ответы с предложением отключить CURLOPT_SSL_VERIFYPEER не следует. Возникает вопрос: «Почему это не работает с cURL», и, как правильно указал Мартин Холс, это опасно.

Ошибка, вероятно, вызвана отсутствием обновленного пакета корневых сертификатов ЦС. Обычно это текстовый файл с набором криптографических подписей, которые curl использует для проверки SSL-сертификата хоста.

Вам необходимо убедиться, что в вашей установке PHP есть один из этих файлов и что он обновлен (в противном случае загрузите его здесь: http://curl.haxx.se/docs/caextract.html ).

Затем установите в php.ini :

curl.cainfo = <absolute_path_to> cacert.pem

Если вы устанавливаете его во время выполнения, используйте:

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

1
Спасибо, но искал предложение по работе с внешним API. Итак, предложение @SabujHassan работает, и, как я понял, API, который я использовал, не предоставляет SSL.
Виктор Бочарский

Отличное решение. Большое спасибо :)
Чандра Накка

1
Работает как по волшебству. Это должен быть ответ, «принятый ответ» - простой, но плохой способ по соображениям безопасности.
KristCont

Спасибо, как сказано, работает отлично! Это действительно должен быть правильный ответ.
PostMans

2
Стоит отметить, что curl.cainfo не отображается в phpinfo () в PHP 7.1 / 7.2, хотя openssl.cafile есть. php.net/manual/en/curl.configuration.php
Элайджа Линн

58

Этот обходной путь опасен и не рекомендуется :

curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);

Отключать одноранговую проверку SSL - не лучшая идея. Это может сделать ваши запросы уязвимыми для злоумышленников MITM.

Фактически, вам просто нужен обновленный комплект корневых сертификатов CA. Установить обновленное так же просто, как:

  1. Скачивание актуального cacert.pemфайла с сайта cURL и

  2. Установка пути к нему в файле php.ini, например, в Windows:

    curl.cainfo=c:\php\cacert.pem

Это оно!

Оставайтесь в безопасности.


5
Вы также можете установить эту опцию в своем коде, если у вас нет прав на редактирование глобального php.iniфайла: curl_setopt ($curl_ch, CURLOPT_CAINFO, dirname(__FILE__)."/cacert.pem");
zxcmehran

2
Работал над средой разработки
cmedeiros

2
Хорошо для тестирования на dev env
Gaurav Rai

Это ужасный совет, и ответ следует удалить.
miken32

4
@ miken32 да, а затем я предлагаю альтернативное безопасное решение в качестве замены опасному обходному пути. Читайте до конца.
zxcmehran 03

3

Если сертификаты SSL не установлены в вашей системе должным образом, вы можете получить такую ​​ошибку:

Ошибка cURL 60: проблема с сертификатом SSL: невозможно получить сертификат местного эмитента.

Вы можете решить эту проблему следующим образом:

Загрузите файл с обновленным списком сертификатов с https://curl.haxx.se/ca/cacert.pem

Переместите загруженный cacert.pemфайл в безопасное место в вашей системе.

Обновите свой php.iniфайл и настройте путь к этому файлу:


Также вам, возможно, придется установить openssl.cafile="C:/dev/ssl/mywebsite.local.crt"­в php.ini
François Breton

3

Важно: эта проблема сводила меня с ума на пару дней, и я не мог понять, что происходит с моими установками curl и openssl. Я наконец понял, что это мой промежуточный сертификат (в моем случае GoDaddy), который устарел. Я вернулся в свою административную панель godaddy SSL, загрузил новый промежуточный сертификат, и проблема исчезла.

Я уверен, что это проблема для некоторых из вас.

Очевидно, GoDaddy в какой-то момент изменил свой промежуточный сертификат из-за проблем с безопасностью, поскольку теперь они отображают это предупреждение:

«Обязательно используйте новые промежуточные сертификаты SHA-2, включенные в загруженный пакет».

Надеюсь, это поможет некоторым из вас, потому что я сходил с ума, и это устранило проблему на ВСЕХ моих серверах.


Хотя это не совсем связано с вопросом, в целом он может предоставить жизнеспособную информацию.
peter.hrasko.sk

Сообщения об ошибках, которые производит curl, иногда могут быть загадочными и вводящими в заблуждение, и я уверен, что некоторые люди, которые получали ошибку «самоподписанного сертификата», получали ее из-за указанной мною причуды. Я также хотел добавить, что при создании curl я использовал строку конфигурации: ./configure --with-ca-bundle = / etc / ssl / certs / ca-bundle.crt, и я также использовал perl-скрипт lib / mk -ca-bundle.pl, чтобы создать красивый свежий файл ca-bundle.crt. Я использовал веб-сервер apache, но я не заменил существующий промежуточный сертификат обновленным от godaddy.
Lee

-3

Ошибка: проблема с сертификатом SSL: самоподписанный сертификат в цепочке сертификатов

Solution:
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);    
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
curl_setopt($ch, CURLOPT_FAILONERROR, 1);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.