可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
I use following PHP function:
file_get_contents(\'http://example.com\');
Whenever I do this on a certain server, the result is empty. When I do it anywhere else, the result is whatever the page\'s content may be. When I however, on the server where the result is empty, use the function locally - without accessing an external URL (file_get_contents(\'../simple/internal/path.html\');
), it does work.
Now, I am pretty sure it has something to do with a certain php.ini configuration. What I am however not sure about is, which one. Please help.
回答1:
The setting you are looking for is allow_url_fopen
.
You have two ways of getting around it without changing php.ini, one of them is to use fsockopen()
, and the other is to use cURL.
I recommend using cURL over file_get_contents()
anyways, since it was built for this.
回答2:
Complementing Aillyn\'s answer, you could use a function like the one below to mimic the behavior of file_get_contents:
function get_content($URL){
$ch = curl_init();
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_URL, $URL);
$data = curl_exec($ch);
curl_close($ch);
return $data;
}
echo get_content(\'http://example.com\');
回答3:
The is related to the ini configuration setting allow_url_fopen
.
You should be aware that enable that option may make some bugs in your code exploitable.
For instance, this failure to validate input may turn into a full-fledged remote code execution vulnerability:
copy($_GET[\"file\"], \".\");
回答4:
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, \"http://www.your_external_website.com\");
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
$result = curl_exec($ch);
curl_close($ch);
is best for http url,
But how to open https url help me
回答5:
The answers provided above solve the problem but don\'t explain the strange behaviour the OP described. This explanation should help anyone testing communication between sites in a development environment where these sites all reside on the same host (and the same virtualhost; I\'m working with apache 2.4 and php7.0).
There\'s a subtlety with file_get_contents()
I came across that is absolutely relevant here but unaddressed (probably because it\'s either barely documented or not documented from what I can tell or is documented in an obscure php security model whitepaper I can\'t find).
With allow_url_fopen
set to Off
in all relevant contexts (e.g. /etc/php/7.0/apache2/php.ini
, /etc/php/7.0/fpm/php.ini
, etc...) and allow_url_fopen
set to On
in the command line context (i.e. /etc/php/7.0/cli/php.ini
), calls to file_get_contents()
for a local resource will be allowed and no warning will be logged such as:
file_get_contents(\'php://input\');
or
// Path outside document root that webserver user agent has permission to read. e.g. for an apache2 webserver this user agent might be www-data so a file at /etc/php/7.0/filetoaccess would be successfully read if www-data had permission to read this file
file_get_contents(\'<file path to file on local machine user agent can access>\');
or
// Relative path in same document root
file_get_contents(\'data/filename.dat\')
To conclude, the restriction allow_url_fopen = Off
is analogous to an iptables
rule in the OUTPUT
chain, where the restriction is only applied when an attempt to \"exit the system\" or \"change contexts\" is made.
N.B. allow_url_fopen
set to On
in the command line context (i.e. /etc/php/7.0/cli/php.ini
) is what I had on my system but I suspect it would have no bearing on the explanation I provided even if it were set to Off
unless of course you\'re testing by running your scripts from the command line itself. I did not test the behaviour with allow_url_fopen
set to Off
in the command line context.
回答6:
This will also give external links an absolute path without having to use php.ini
<?php
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, \"http://www.your_external_website.com\");
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
$result = curl_exec($ch);
curl_close($ch);
$result = preg_replace(\"#(<\\s*a\\s+[^>]*href\\s*=\\s*[\\\"\'])(?!http)([^\\\"\'>]+)([\\\"\'>]+)#\",\'$1http://www.your_external_website.com/$2$3\', $result);
echo $result
?>
回答7:
Add:
allow_url_fopen=1
in your php.ini
file. If you are using shared hosting, create one first.