4

构建自引用 URL 的最可靠、最通用的方法是什么?换句话说,我想生成用户浏览器正在点击的 URL 的http://www.site.com[:port]部分。我正在使用在 Apache 下运行的 PHP。

一些并发症:

  • 依赖 $_SERVER["HTTP_HOST"] 是危险的,因为这似乎直接来自 HTTP Host 标头,有人可以伪造。

  • 可能有也可能没有虚拟主机。

  • 可能有一个使用 Apache 的 Port 指令指定的端口,但如果它位于负载平衡器或代理之后,则该端口可能不是用户指定的端口。

  • 该端口实际上可能不是 URL 的一部分。例如,通常省略 80 和 443。

  • PHP 的 $_SERVER["HTTPS"] 并不总是提供可靠的值,尤其是当您使用负载平衡器或代理时。

  • Apache 有一个 UseCanonicalName 指令,它会影响 SERVER_NAME 和 SERVER_PORT 环境变量的值。如果有帮助,我们可以假设它已打开。

4

6 回答 6

2

我记得,你想做这样的事情:

$protocol = 'http';

if ( (!empty($_SERVER['HTTPS'])) || ($_SERVER['HTTPS'] == 'off') ) {
    $protocol = 'https';
    if ($_SERVER['SERVER_PORT'] != 443)
        $port = $_SERVER['SERVER_PORT'];
} else if ($_SERVER['SERVER_PORT'] != 80) {
    $port = $_SERVER['SERVER_PORT'];
}
// Server name is going to be whatever the virtual host name is set to in your configuration
$address = $protocol . '://' . $_SERVER['SERVER_NAME'];
if (!empty($port))
    $address .= ':' . $port
$address .= $_SERVER['REQUEST_URI'];
// Optional, if you want the query string intact
if (!empty($_SERVER['QUERY_STRING']))
    $address .= '?' . $_SERVER['QUERY_STRING'];

我还没有测试过这段代码,因为我现在手头没有 PHP。

于 2009-01-28T21:45:58.643 回答
2

我建议确定和确保安全的唯一方法是在网站的某种配置文件中为 url 定义一个常量。您可以使用 $_SERVER['HTTP_HOST'] 作为默认值生成常量,并在安全性真正重要的部署中替换为硬编码定义。

define('SITE_URL', $_SERVER['HTTP_HOST']);

并根据需要更换:

define('SITE_URL', 'http://foo.bar.com:8080/');
于 2009-01-28T21:48:32.227 回答
1

最可靠的方法是自己提供。

该站点应编码为与主机名无关,但要了解特殊的配置文件。该文件不会被放入代码库的源代码控制中,因为它属于网络服务器的配置。该文件用于设置主机名和其他特定于网络服务器的参数。您可以容纳负载平衡器、更改端口等,因为您是说如果 HTTP 请求命中该代码,那么它可以假设您愿意假设多少。

顺便说一句,这个技巧也有助于开发。:-)

于 2009-01-28T22:08:30.377 回答
0

$_SERVER["HTTP_HOST"] 可能是最好的方法,当然经过一些验证。

是的,用户指定了它,因此它不可信,但您可以轻松检测到用户何时使用它玩游戏。

于 2009-01-28T21:38:58.750 回答
0

验证 $_SERVER['HTTP_HOST'] 有效的一种方法是通过 DNS 验证它。我已经在一两种情况下使用了这种方法,而没有对速度造成严重后果,我相信如果提供 IP 地址,这种方法会静默失败。

http://www.php.net/manual/en/function.gethostbyname.php

Peusudo 代码可能是:

define('SITEHOME', in_array(gethostbyname($_SERVER['HTTP_HOST']), array(... valid IP's))) 
? $_SERVER['HTTP_HOST']
: 'default_hostname';
于 2009-01-28T22:02:55.177 回答
0

为什么{如果您希望用户继续使用他们所在的http:///host:port/您是否希望生成完整的 url} 可以使用相对 url 而不是

在http://xxx:yy/zzz/fff/页面上说

你可以使用

../graphics/whatever.jpg {to go back one directory from current and get http://xxx:yy/zzz/graphics/whatever.jpg

or /zzz/graphics/whatever.jpg {to goto site root and work up the directories as specified}

these both avoid mentioning the host:port part and inherit it from the one currently in use

于 2009-01-29T00:45:36.737 回答