file_get_contents () : 코드 1로 SSL 작업 실패, 암호화 사용 실패
서버에서 만든 PHP 페이지에서이 특정 REST 서비스에 액세스하려고했습니다. 문제를이 두 줄로 좁혔습니다. 그래서 내 PHP 페이지는 다음과 같습니다
<?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; ?>
페이지가 2 행에서 다음 오류와 함께 종료됩니다.
- 경고 : file_get_contents () : 코드 1로 SSL 작업 실패
- 경고 : file_get_contents () : 2 행의 ... php에서 암호화를 활성화하지 못했습니다.
- 경고 : 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) : 스트림을 열지 못했습니다 : 2 행의 ... php에서 작업이 실패했습니다.
우리는 젠투 서버를 사용하고 있습니다. 최근에 PHP 버전 5.6으로 업그레이드했습니다. 이 문제가 나타 났을 때 업그레이드 이후였습니다.
REST 서비스를 다음과 같은 주소로 바꿀 때 찾았습니다 https://www.google.com. 내 페이지가 잘 작동합니다.
이전 시도에서 나는을 설정 “verify_peer”=>false하고 여기에 설명 된대로 file_get_contents에 인수로 전달했습니다. verify_peer => false? 그러나 작가가 지적한 것처럼; 아무런 차이가 없었습니다.
php.ini 파일에 다음 줄이 있는지 서버 관리자에게 물었습니다.
- extension = php_openssl.dll
- allow_url_fopen = 켜기
그는 Gentoo를 사용하고 있기 때문에 우리가 빌드 할 때 openssl이 컴파일된다고 말했습니다. php.ini 파일에 설정되어 있지 않습니다.
또한 allow_url_fopen작동하고 있음을 확인했습니다 . 이 문제의 특수한 특성으로 인해; 도움이 필요한 정보를 많이 찾지 못했습니다. 이런 사람이 있습니까? 감사.
이것은 다음을 찾는 데 매우 유용한 링크였습니다.
http://php.net/manual/en/migration56.openssl.php
PHP 5.6에서 ssl을 여는 변경 사항을 설명하는 공식 문서 여기에서 내가 false로 설정해야하는 하나 이상의 매개 변수에 대해 배웠습니다. "verify_peer_name"=> false
참고 : 이것은 보안에 매우 중요한 영향을 미칩니다. 확인을 비활성화하면 MITM 공격자 가 잘못된 인증서를 사용하여 요청을 도청 할 수 있습니다. 로컬 개발에서이 작업을 수행하는 것이 유용 할 수 있지만 프로덕션에서는 다른 접근 방식을 사용해야합니다.
작업 코드는 다음과 같습니다.
<?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; ?>
확인 만 끄면 안됩니다. 오히려 컬 번들이 할 인증서 번들을 다운로드 해야합니까?
그런 다음 웹 서버에 저장하면 PHP를 실행하는 사용자에게 파일을 읽을 수있는 권한을 부여 할 수 있습니다. 그런 다음이 코드가 효과가 있습니다.
$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));
다행히도 액세스하려는 사이트의 루트 인증서가 curl 번들에 있습니다. 그렇지 않은 경우 사이트의 루트 인증서를 얻어 인증서 파일에 넣을 때까지 여전히 작동하지 않습니다.
OpenSSL이 내 컴퓨터에 설치되어 있는지 확인한 다음 이것을 php.ini에 추가하여 문제를 해결했습니다.
openssl.cafile=/usr/local/etc/openssl/cert.pem
다음과 같이 curl을 사용하는 사용자 정의 함수를 작성하여이 문제를 해결할 수 있습니다.
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;
}
그런 다음 https로 시작하는 URL을 호출 할 때마다 file_get_contents_curl대신 사용 file_get_contents하십시오.
PHP 버전이 5 인 경우 터미널에 다음 명령을 입력하여 cURL을 설치하십시오.
sudo apt-get install php5-curl
You basically have to set the environment variable SSL_CERT_FILE to the path of the PEM file of the ssl-certificate downloaded from the following link : http://curl.haxx.se/ca/cacert.pem.
It took me a lot of time to figure this out.
following below steps will fix this issue,
- Download the CA Certificate from this link: https://curl.haxx.se/ca/cacert.pem
- Find and open php.ini
- Look for
curl.cainfoand paste the absolute path where you have download the Certificate.curl.cainfo ="C:\wamp\htdocs\cert\cacert.pem" - Restart WAMP/XAMPP (apache server).
- It works!
hope that helps !!
Working for me, I am using PHP 5.6. openssl extension should be enabled and while calling google map api verify_peer make false Below code is working for me.
<?php
$arrContextOptions=array(
"ssl"=>array(
"verify_peer"=>false,
"verify_peer_name"=>false,
),
);
$response = file_get_contents("https://maps.googleapis.com/maps/api/geocode /json?latlng=" . $latitude . "," . $longitude . "&sensor=false&key=" . Yii::$app->params['GOOGLE_API_KEY'], false, stream_context_create($arrContextOptions));
echo $response; ?>
Just wanted to add to this since I ran into the same problem and nothing I could find anywhere would work (e.g downloading the cacert.pem file, setting cafile in php.ini etc.)
If you are using NGINX and your SSL certificate comes with an "intermediate certificate", you need to combine the intermediate cert file with your main "mydomain.com.crt" file and it should work. Apache has a setting specific for intermediate certs, but NGINX does not so it must be within same file as your regular cert.
Reason for this error is that PHP does not have a list of trusted certificate authorities.
PHP 5.6 and later try to load the CAs trusted by the system automatically. Issues with that can be fixed. See http://php.net/manual/en/migration56.openssl.php for more information.
PHP 5.5 and earlier are really hard to setup correctly since you manually have to specify the CA bundle in each request context, a thing you do not want to sprinkle around your code. So I decided for my code that for PHP versions < 5.6, SSL verification simply gets disabled:
$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);
}
Had the same error with PHP 7 on XAMPP and OSX.
The above mentioned answer in https://stackoverflow.com/ is good, but it did not completely solve the problem for me. I had to provide the complete certificate chain to make file_get_contents() work again. That's how I did it:
Get root / intermediate certificate
First of all I had to figure out what's the root and the intermediate certificate.
The most convenient way is maybe an online cert-tool like the ssl-shopper
There I found three certificates, one server-certificate and two chain-certificates (one is the root, the other one apparantly the intermediate).
All I need to do is just search the internet for both of them. In my case, this is the root:
thawte DV SSL SHA256 CA
And it leads to his url thawte.com. So I just put this cert into a textfile and did the same for the intermediate. Done.
Get the host certificate
Next thing I had to to is to download my server cert. On Linux or OS X it can be done with openssl:
openssl s_client -showcerts -connect whatsyoururl.de:443 </dev/null 2>/dev/null|openssl x509 -outform PEM > /tmp/whatsyoururl.de.cert
Now bring them all together
Now just merge all of them into one file. (Maybe it's good to just put them into one folder, I just merged them into one file). You can do it like this:
cat /tmp/thawteRoot.crt > /tmp/chain.crt
cat /tmp/thawteIntermediate.crt >> /tmp/chain.crt
cat /tmp/tmp/whatsyoururl.de.cert >> /tmp/chain.crt
tell PHP where to find the chain
There is this handy function openssl_get_cert_locations() that'll tell you, where PHP is looking for cert files. And there is this parameter, that will tell file_get_contents() where to look for cert files. Maybe both ways will work. I preferred the parameter way. (Compared to the solution mentioned above).
So this is now my PHP-Code
$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));
That's all. file_get_contents() is working again. Without CURL and hopefully without security flaws.
Had the same ssl-problem on my developer machine (php 7, xampp on windows) with a self signed certificate trying to fopen a "https://localhost/..."-file. Obviously the root-certificate-assembly (cacert.pem) didn't work. I just copied manually the code from the apache server.crt-File in the downloaded cacert.pem and did the openssl.cafile=path/to/cacert.pem entry in php.ini
After falling victim to this problem on centOS after updating php to php5.6 I found a solution that worked for me.
Get the correct directory for your certs to be placed by default with this
php -r 'print_r(openssl_get_cert_locations()["default_cert_file"]);'
Then use this to get the cert and put it in the default location found from the code above
wget http://curl.haxx.se/ca/cacert.pem -O <default location>
Another thing to try is to re-install ca-certificates as detailed here.
# yum reinstall ca-certificates
...
# update-ca-trust force-enable
# update-ca-trust extract
And another thing to try is to explicitly allow the one site's certificate in question as described here (especially if the one site is your own server and you already have the .pem in reach).
# cp /your/site.pem /etc/pki/ca-trust/source/anchors/
# update-ca-trust extract
I was running into this exact SO error after upgrading to PHP 5.6 on CentOS 6 trying to access the server itself which has a cheapsslsecurity certificate which maybe it needed to be updated, but instead I installed a letsencrypt certificate and with these two steps above it did the trick. I don't know why the second step was necessary.
Useful Commands
View openssl version:
# openssl version
OpenSSL 1.0.1e-fips 11 Feb 2013
View PHP cli ssl current settings:
# php -i | grep ssl
openssl
Openssl default config => /etc/pki/tls/openssl.cnf
openssl.cafile => no value => no value
openssl.capath => no value => no value
Regarding errors similar to
[11-May-2017 19:19:13 America/Chicago] PHP Warning: file_get_contents(): SSL operation failed with code 1. OpenSSL Error messages: error:14090086:SSL routines:ssl3_get_server_certificate:certificate verify failed
Have you checked the permissions of the cert and directories referenced by openssl?
You can do this
var_dump(openssl_get_cert_locations());
To get something similar to this
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) ""
}
This issue frustrated me for a while, until I realized that my "certs" folder had 700 permissions, when it should have had 755 permissions. Remember, this is not the folder for keys but certificates. I recommend reading this this link on ssl permissions.
Once I did
chmod 755 certs
The problem was fixed, at least for me anyway.
I had the same issue for another secure page when using wget or file_get_contents. A lot of research (including some of the responses on this question) resulted in a simple solution - installing Curl and PHP-Curl - If I've understood correctly, Curl has the Root CA for Comodo which resolved the issue
Install Curl and PHP-Curl addon, then restart Apache
sudo apt-get install curl
sudo apt-get install php-curl
sudo /etc/init.d/apache2 reload
All now working.
'Programming' 카테고리의 다른 글
| HttpContent 사용 방법을 찾을 수 없습니다 (0) | 2020.06.02 |
|---|---|
| '선언되지 않은 선택기'경고를 제거하는 방법 (0) | 2020.06.02 |
| NavigationView get / find 헤더 레이아웃 (0) | 2020.06.02 |
| XSD와 WSDL의 차이점은 무엇입니까 (0) | 2020.06.01 |
| 문자열에 숫자 만 포함되어 있는지 확인하는 가장 빠른 방법 (0) | 2020.06.01 |