使用HTTP基本身份验证进行HTTP GET请求

36

我需要为我正在进行的Flash Player项目构建一个代理。我只需要对另一个URL进行HTTP GET请求并使用HTTP基本身份验证,然后将PHP的响应作为原始来源提供。我该如何实现?


您需要一个全PHP解决方案,还是可以调用curl进行外部调用? - Peter
如果curl很容易获取,我可能会使用它。我希望我的脚本在尽可能多的机器上“只需工作”。 - Naftuli Kay
curl非常容易获得,虽然您当然需要为每个目标平台操作系统重新编译源代码。我使用curl的主要优点是:1)“开箱即用”支持复杂功能(如带有身份验证的HTTP代理和客户端证书),以及2)诊断(可帮助您找出某些HTTP事务失败的原因)。 - Peter
4个回答

115

Marc B的回答非常好。我最近采用了他的方法,并想分享结果代码。

<?PHP

$username = "some-username";
$password = "some-password";
$remote_url = 'http://www.somedomain.com/path/to/file';

// Create a stream
$opts = array(
  'http'=>array(
    'method'=>"GET",
    'header' => "Authorization: Basic " . base64_encode("$username:$password")                 
  )
);

$context = stream_context_create($opts);

// Open the file using the HTTP headers set above
$file = file_get_contents($remote_url, false, $context);

print($file);

?>

我希望这对人们有所帮助!


7
不,他回答问题做得很差。你做得很好。(投票结果证明了我的观点!) - miken32

14

17
+1 - 还要注意,如果您没有流支持(PHP4)或cURL扩展不可用,则可以使用http://user:pass@domain.tld/file URL语法与file_get_contents(),它将提供HTTP基本身份验证功能。 - DaveRandom
1
@DaveRandom 更好的是,太棒了。 - Naftuli Kay
1
你能用PHP给个例子吗?我有点卡住了,尝试了几种不同的方法但都没有成功。 - Naftuli Kay
你能具体说明一下你尝试过什么吗?file_get_contents()的手册中有一些没有HTTP基本身份验证的示例,它们对你是否有效?如果是这样,并且添加auth前缀由于某种原因失败了,那么你可以从print_r(error_get_last())中获得一些提示。 - Peter
@DaveRandom的解决方案是将凭据放在URL中,这个方法很好,除非从http重定向到https。在这种情况下,PHP会“丢失”请求https URL的凭据。但如果它们在上下文中,它们仍然会被使用。 - Den

4
我将@clone45的代码转换成了一系列函数,有点像Python的requests接口(对我的目的来说足够了),只使用了没有外部代码。也许它可以帮助其他人。
它处理以下内容:
- 基本认证 - 标头 - GET参数

用法:

$url = 'http://sweet-api.com/api';
$params = array('skip' => 0, 'top' => 5000);
$header = array('Content-Type' => 'application/json');
$header = addBasicAuth($header, getenv('USER'), getenv('PASS'));
$response = request("GET", $url, $header, $params);
print($response);

定义

function addBasicAuth($header, $username, $password) {
    $header['Authorization'] = 'Basic '.base64_encode("$username:$password");
    return $header;
}

// method should be "GET", "PUT", etc..
function request($method, $url, $header, $params) {
    $opts = array(
        'http' => array(
            'method' => $method,
        ),
    );

    // serialize the header if needed
    if (!empty($header)) {
        $header_str = '';
        foreach ($header as $key => $value) {
            $header_str .= "$key: $value\r\n";
        }
        $header_str .= "\r\n";
        $opts['http']['header'] = $header_str;
    }

    // serialize the params if there are any
    if (!empty($params)) {
        $params_array = array();
        foreach ($params as $key => $value) {
            $params_array[] = "$key=$value";
        }
        $url .= '?'.implode('&', $params_array);
    }

    $context = stream_context_create($opts);
    $data = file_get_contents($url, false, $context);
    return $data;
}

太好了,谢谢。如果响应带有链接怎么办?当响应页面上的链接被点击时,我如何使用链接URL调用请求函数? - Sadık
@Sadik 如果响应中包含链接,您需要从获取的字符串中解析它们。例如,如果是JSON格式,您可以使用json_decode函数。 - Ben

-14
你真的想用 PHP 来做那个吗?
一个简单的 JavaScript 脚本就可以实现:
function login(username, password, url) {

  var http = getHTTPObject();

  http.open("get", url, false, username, password);
  http.send("");
  //alert ("HTTP status : "+http.status);

  if (http.status == 200) {
    //alert ("New window will be open");
    window.open(url, "My access", "width=200,height=200", "width=300,height=400,scrollbars=yes");
    //win.document.location = url;
  } else {
    alert("No access to the secured web site");
  }

}

function getHTTPObject() { 

  var xmlhttp = false;
  if (typeof XMLHttpRequest != 'undefined') {
    try {
      xmlhttp = new XMLHttpRequest();
    } catch (e) {
      xmlhttp = false;
    }
  } else {
    /*@cc_on
    @if (@_jscript_version >= 5)
    try {
      xmlhttp = new ActiveXObject("Msxml2.XMLHTTP");
    } catch (e) {
      try {
        xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
      } catch (E) {
        xmlhttp = false;
      }
    }
    @end @*/
  }
  return xmlhttp;
}

正在开发一个旨在跨站共享的项目,因此不幸的是,任何外部JavaScript都无法使用,需要一个托管所有PHP解决方案。 - Naftuli Kay

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