file_get_contents在代理后面怎么使用?

79

在工作中,我们必须使用代理来访问端口80,例如,我们为每个用户设置了自己的自定义登录。

我的临时解决方法是使用curl通过代理登录并访问我需要的外部数据。

是否有一种高级的php设置,可以在内部每当尝试调用像file_get_contents()这样的东西时,它总是通过代理进行?我现在正在使用Windows,如果那是唯一的方法,那将会很麻烦重新编译。

我的解决方法是临时的,因为我需要一个通用的解决方案,适用于多个用户,而不是使用一个用户的凭据(我考虑过请求单独的用户帐户来执行此操作,但密码经常更改,而且这种技术需要在十几个或更多站点上部署)。我不想硬编码凭据以使用curl解决方法。

4个回答

182
要使用不需要身份认证的代理服务器使用 file_get_contents(),可以尝试以下代码:

(我无法测试此代码:我的代理服务器需要身份认证)

$aContext = array(
    'http' => array(
        'proxy'           => 'tcp://192.168.0.2:3128',
        'request_fulluri' => true,
    ),
);
$cxContext = stream_context_create($aContext);

$sFile = file_get_contents("http://www.google.com", False, $cxContext);

echo $sFile;

当然,将我的代理的IP和端口替换为适合您的IP和端口;-)

如果您遇到了这种错误:

Warning: file_get_contents(http://www.google.com) [function.file-get-contents]: failed to open stream: HTTP request failed! HTTP/1.0 407 Proxy Authentication Required

这意味着您的代理服务器需要进行身份验证。

如果代理服务器需要进行身份验证,您需要添加以下几行代码:

$auth = base64_encode('LOGIN:PASSWORD');

$aContext = array(
    'http' => array(
        'proxy'           => 'tcp://192.168.0.2:3128',
        'request_fulluri' => true,
        'header'          => "Proxy-Authorization: Basic $auth",
    ),
);
$cxContext = stream_context_create($aContext);

$sFile = file_get_contents("http://www.google.com", False, $cxContext);

echo $sFile;

这里涉及到IP地址和端口,而且还需要使用登录名和密码;-)查看所有有效的http选项

现在,您正在向代理传递一个包含您的登录和密码的Proxy-Authorization头。

然后...页面应该显示出来了 ;-)


Martin,我有一个代理自动配置(PAC)文件,而不是单个代理服务器。此外,它需要NTLM身份验证。你能帮我解决一下吗? - codeomnitrix
我遇到了以下错误:无法打开流:无法找到套接字传输“http” - 配置PHP时是否忘记启用它?我正在使用启用curl的PHP5.5 / Apache2.4。 - Tuan Anh Hoang-Vu
非常感谢。通常情况下,cURL 能够满足我的需求,但是我正在尝试使用 Appengine PHP,并且没有 cURL,所以使用带有流上下文的 file_get_content 已经帮了我大忙 :D - m3nda
@codeomnitrix,可能有点晚了,但我也遇到了同样的问题,我在浏览器中粘贴了pac文件的url,在文件中找到了代理IP地址。 - Martin Lietz
1
对于任何人:在我的情况下,使用tcp作为协议也是必要的。之前我使用了http,导致出现错误:failed to open stream: Unable to find the socket transport "http" - did you forget to enable it when you configured PHP? - robsch
如果有人使用此功能出现“400 Bad Request”的情况,请尝试禁用非标准的“request_fulluri”。 - Trendfischer

24

使用 stream_context_set_default 函数。这样可以更容易地使用 file_get_contents 或类似的函数,而无需传递任何额外的参数。

这篇博客文章解释了如何使用它。以下是该页面的代码:

<?php
// Edit the four values below
$PROXY_HOST = "proxy.example.com"; // Proxy server address
$PROXY_PORT = "1234";    // Proxy server port
$PROXY_USER = "LOGIN";    // Username
$PROXY_PASS = "PASSWORD";   // Password
// Username and Password are required only if your proxy server needs basic authentication

$auth = base64_encode("$PROXY_USER:$PROXY_PASS");
stream_context_set_default(
 array(
  'http' => array(
   'proxy' => "tcp://$PROXY_HOST:$PROXY_PORT",
   'request_fulluri' => true,
   'header' => "Proxy-Authorization: Basic $auth"
   // Remove the 'header' option if proxy authentication is not required
  )
 )
);

$url = "http://www.pirob.com/";

print_r( get_headers($url) );

echo file_get_contents($url);
?>

非常晚的评论,但是**不要使用stream_context_set_default**:它会影响整个PHP服务器,可能会破坏其他使用http流包装器的库。 - Christian

3
根据代理登录的工作方式,stream_context_set_default 可能会对您有所帮助。请注意保留 HTML 标签。
$context  = stream_context_set_default(
  array(
    'http'=>array(
      'header'=>'Authorization: Basic ' . base64_encode('username'.':'.'userpass')
    )
  )
);
$result = file_get_contents('http://..../...');

2
这里有一个类似的帖子:http://techpad.co.uk/content.php?sid=137,其中解释了如何操作。
function file_get_contents_proxy($url,$proxy){

    // Create context stream
    $context_array = array('http'=>array('proxy'=>$proxy,'request_fulluri'=>true));
    $context = stream_context_create($context_array);

    // Use context stream with file_get_contents
    $data = file_get_contents($url,false,$context);

    // Return data via proxy
    return $data;

}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接