php - tls_process_server_certificate - file_get_contents(): la operación SSL falló con el código 1. Y más
ssl routines:tls_process_server_certificate:certificate verify failed (14)
Básicamente, debe establecer la variable de entorno SSL_CERT_FILE en la ruta del archivo PEM del certificado ssl descargado del siguiente enlace: http://curl.haxx.se/ca/cacert.pem .
Me tomó mucho tiempo resolver esto.
He intentado acceder a este servicio REST en particular desde una página PHP que he creado en nuestro servidor. Reduje el problema a estas dos líneas. Entonces mi página PHP se ve así:
<?php
$response = file_get_contents("https://maps.co.weber.ut.us/arcgis/rest/services/SDE_composite_locator/GeocodeServer/findAddressCandidates?Street=&SingleLine=3042+N+1050+W&outFields=*&outSR=102100&searchExtent=&f=json");
echo $response; ?>
La página muere en la línea 2 con los siguientes errores:
- Advertencia: file_get_contents (): la operación SSL falló con el código 1. Mensajes de error de OpenSSL: error: 14090086: rutinas SSL: SSL3_GET_SERVER_CERTIFICATE: la verificación del certificado falló en ... php en la línea 2
- Advertencia: file_get_contents (): Error al habilitar crypto en ... php en la línea 2
- Advertencia: file_get_contents (
https://maps.co.weber.ut.us/arcgis/rest/services/SDE_composite_locator/GeocodeServer/findAddressCandidates?Street=&SingleLine=3042+N+1050+W&outFields=*&outSR=102100&searchExtent=&f=json
): no se pudo abrir la secuencia: la operación falló en ... php en la línea 2
Estamos usando un servidor de Gentoo. Recientemente hemos actualizado a PHP versión 5.6. Fue después de la actualización cuando apareció este problema.
Encontré cuando reemplazo el servicio REST con una dirección como https://www.google.com
; mi página funciona bien.
En un intento anterior, configuré “verify_peer”=>false
, y pasé eso como un argumento para file_get_contents, como se describe aquí: file_get_contents ignorando verify_peer => false? Pero como el escritor señaló; no hizo ninguna diferencia.
Le pregunté a uno de nuestros administradores del servidor si existen estas líneas en nuestro archivo php.ini:
- extension = php_openssl.dll
- allow_url_fopen = On
Me dijo que ya que estamos en Gentoo, openssl se compila cuando compilamos; y no está establecido en el archivo php.ini.
También confirmó que allow_url_fopen
está funcionando. Debido a la naturaleza especializada de este problema; No encuentro mucha información para obtener ayuda. ¿Alguno de ustedes se ha encontrado con algo como esto? Gracias.
Después de ser víctima de este problema en centOS después de actualizar php a php5.6 encontré una solución que funcionó para mí.
Obtenga el directorio correcto para que sus certs sean colocados por defecto con esto
php -r ''print_r(openssl_get_cert_locations());'' | grep ''/[default_cert_file/]'' | awk ''{print $3}''
Luego, use esto para obtener el certificado y colóquelo en la ubicación predeterminada que se encuentra en el código anterior
wget http://curl.haxx.se/ca/cacert.pem -O <default location>
En cuanto a los errores similares a
[11-May-2017 19:19:13 America / Chicago] Advertencia de PHP: file_get_contents (): la operación SSL falló con el código 1. Mensajes de error de OpenSSL: error: 14090086: rutinas SSL: ssl3_get_server_certificate: verificación de certificado fallida
¿Has revisado los permisos del certificado y los directorios a los que se hace referencia en openssl?
Puedes hacerlo
var_dump(openssl_get_cert_locations());
Para obtener algo similar a esto
array(8) {
["default_cert_file"]=>
string(21) "/usr/lib/ssl/cert.pem"
["default_cert_file_env"]=>
string(13) "SSL_CERT_FILE"
["default_cert_dir"]=>
string(18) "/usr/lib/ssl/certs"
["default_cert_dir_env"]=>
string(12) "SSL_CERT_DIR"
["default_private_dir"]=>
string(20) "/usr/lib/ssl/private"
["default_default_cert_area"]=>
string(12) "/usr/lib/ssl"
["ini_cafile"]=>
string(0) ""
["ini_capath"]=>
string(0) ""
}
Este problema me frustró por un tiempo, hasta que me di cuenta de que mi carpeta "certs" tenía 700 permisos, cuando debería haber tenido 755 permisos. Recuerde, esta no es la carpeta para las claves sino los certificados. Recomiendo leer este enlace en los permisos ssl.
Una vez que lo hice
chmod 755 certs
El problema se solucionó, al menos para mí de todos modos.
Este fue un enlace enormemente útil para encontrar:
http://php.net/manual/en/migration56.openssl.php
Un documento oficial que describe los cambios realizados para abrir ssl en PHP 5.6. Desde aquí aprendí de un parámetro más que debería haber establecido en falso: "verify_peer_name" => false
Entonces mi código de trabajo se ve así:
<?php
$arrContextOptions=array(
"ssl"=>array(
"verify_peer"=>false,
"verify_peer_name"=>false,
),
);
$response = file_get_contents("https://maps.co.weber.ut.us/arcgis/rest/services/SDE_composite_locator/GeocodeServer/findAddressCandidates?Street=&SingleLine=3042+N+1050+W&outFields=*&outSR=102100&searchExtent=&f=json", false, stream_context_create($arrContextOptions));
echo $response; ?>
La razón de este error es que PHP no tiene una lista de autoridades de certificación confiables.
PHP 5.6 y versiones posteriores intentan cargar las CA confiables por el sistema automáticamente. Problemas con eso pueden ser corregidos. Consulte http://php.net/manual/en/migration56.openssl.php para obtener más información.
PHP 5.5 y versiones anteriores son realmente difíciles de configurar correctamente ya que usted debe especificar manualmente el paquete de CA en cada contexto de solicitud, algo que no desea esparcir alrededor de su código. Así que decidí por mi código que para las versiones PHP <5.6, la verificación SSL simplemente se desactiva:
$req = new HTTP_Request2($url);
if (version_compare(PHP_VERSION, ''5.6.0'', ''<'')) {
//correct ssl validation on php 5.5 is a pain, so disable
$req->setConfig(''ssl_verify_host'', false);
$req->setConfig(''ssl_verify_peer'', false);
}
Lo solucioné al asegurarme de que OpenSSL estaba instalado en mi máquina y luego agregar esto a mi php.ini:
openssl.cafile=/usr/local/etc/openssl/cert.pem
No deberías simplemente desactivar la verificación. En su lugar, debería descargar un paquete de certificados, ¿tal vez el paquete de curl servirá?
Luego solo tiene que ponerlo en su servidor web, dando al usuario que ejecuta el permiso php para leer el archivo. Entonces este código debería funcionar para usted:
$arrContextOptions=array(
"ssl"=>array(
"cafile" => "/path/to/bundle/cacert.pem",
"verify_peer"=> true,
"verify_peer_name"=> true,
),
);
$response = file_get_contents("https://maps.co.weber.ut.us/arcgis/rest/services/SDE_composite_locator/GeocodeServer/findAddressCandidates?Street=&SingleLine=3042+N+1050+W&outFields=*&outSR=102100&searchExtent=&f=json", false, stream_context_create($arrContextOptions));
Es de esperar que el certificado raíz del sitio al que intenta acceder esté en el paquete curl. Si no es así, esto no funcionará hasta que obtenga el certificado raíz del sitio y lo ponga en su archivo de certificado.
Puede solucionar este problema escribiendo una función personalizada que utiliza curl, como en:
function file_get_contents_curl( $url ) {
$ch = curl_init();
curl_setopt( $ch, CURLOPT_AUTOREFERER, TRUE );
curl_setopt( $ch, CURLOPT_HEADER, 0 );
curl_setopt( $ch, CURLOPT_RETURNTRANSFER, 1 );
curl_setopt( $ch, CURLOPT_URL, $url );
curl_setopt( $ch, CURLOPT_FOLLOWLOCATION, TRUE );
$data = curl_exec( $ch );
curl_close( $ch );
return $data;
}
Luego solo use file_get_contents_curl
lugar de file_get_contents
cada vez que llame a una url que comience con https.
Si su versión de PHP es 5, intente instalar cURL escribiendo el siguiente comando en la terminal:
sudo apt-get install php5-curl
Solo quería agregar a esto, ya que me encontré con el mismo problema y nada de lo que podía encontrar funciona (por ejemplo, descargando el archivo cacert.pem, configurando cafile en php.ini, etc.)
Si está utilizando NGINX y su certificado SSL viene con un "certificado intermedio", necesita combinar el archivo cert intermedio con su archivo principal "mydomain.com.crt" y debería funcionar. Apache tiene una configuración específica para certs intermedios, pero NGINX no, por lo que debe estar dentro del mismo archivo que su cert normal.
Tuve el mismo error con PHP 7 en XAMPP y OSX.
La respuesta antes mencionada en https://.com/ es buena, pero no resolvió completamente el problema para mí. Tuve que proporcionar la cadena de certificados completa para hacer que file_get_contents () vuelva a funcionar. Así es como lo hice:
Obtener certificado raíz / intermedio
Primero que nada tuve que averiguar cuál es la raíz y el certificado intermedio.
La forma más conveniente es tal vez una herramienta de certificación en línea como el ssl-shopper
Allí encontré tres certificados, un certificado de servidor y dos certificados de cadena (uno es la raíz, el otro al parecer el intermedio).
Todo lo que necesito hacer es buscar en Internet para ambos. En mi caso, esta es la raíz:
thawte DV SSL SHA256 CA
Y lleva a su url thawte.com . Así que simplemente puse este certificado en un archivo de texto e hice lo mismo para el intermedio. Hecho.
Obtener el certificado de host
Lo siguiente que tuve que hacer es descargar mi certificado de servidor. En Linux o OS X se puede hacer con openssl:
openssl s_client -showcerts -connect whatsyoururl.de:443 </dev/null 2>/dev/null|openssl x509 -outform PEM > /tmp/whatsyoururl.de.cert
Ahora júntalos a todos
Ahora solo fusiona todos en un archivo. (Tal vez es bueno simplemente ponerlos en una carpeta, simplemente los fusioné en un solo archivo). Puedes hacerlo así:
cat /tmp/thawteRoot.crt > /tmp/chain.crt
cat /tmp/thawteIntermediate.crt >> /tmp/chain.crt
cat /tmp/tmp/whatsyoururl.de.cert >> /tmp/chain.crt
decirle a PHP dónde encontrar la cadena
Existe esta práctica función openssl_get_cert_locations () que te dirá, donde PHP está buscando archivos cert. Y existe este parámetro, que le indicará a file_get_contents () dónde buscar los archivos cert. Quizás ambas formas funcionarán. Yo preferí el modo de parámetro. (En comparación con la solución mencionada anteriormente).
Así que este es ahora mi código PHP
$arrContextOptions=array(
"ssl"=>array(
"cafile" => "/Applications/XAMPP/xamppfiles/share/openssl/certs/chain.pem",
"verify_peer"=> true,
"verify_peer_name"=> true,
),
);
$response = file_get_contents($myHttpsURL, 0, stream_context_create($arrContextOptions));
Eso es todo. file_get_contents () está trabajando nuevamente. Sin CURL y con suerte sin fallas de seguridad.
Tuve el mismo problema con otra página segura cuando uso wget
o file_get_contents
. Una gran cantidad de investigaciones (incluidas algunas de las respuestas sobre esta pregunta) dieron como resultado una solución simple: la instalación de Curl y PHP-Curl. Si entendí correctamente, Curl tiene la CA raíz para Comodo que resolvió el problema.
Instale el complemento Curl y PHP-Curl, luego reinicie Apache
sudo apt-get install curl
sudo apt-get install php-curl
sudo /etc/init.d/apache2 reload
Todos ahora trabajando.
Tuve el mismo problema de SSL en mi máquina de desarrollo (php 7, xampp en Windows) con un certificado autofirmado que intenta abrir un archivo " https://localhost/ ...". Obviamente, el root-certificate-assembly (cacert.pem) no funcionó. Acabo de copiar manualmente el código de apache server.crt-File en el cacert.pem descargado e hice la entrada openssl.cafile = path / to / cacert.pem en php.ini
seguir los pasos a continuación solucionará este problema,
- Descargue el certificado de CA desde este enlace: https://curl.haxx.se/ca/cacert.pem
- Encuentra y abre php.ini
- Busque
curl.cainfo
y pegue la ruta absoluta donde ha descargado el certificado.curl.cainfo ="C:/wamp/htdocs/cert/cacert.pem"
- Reinicie WAMP / XAMPP (servidor apache).
- ¡Funciona!
Espero que ayude !!