8

我正在寻找一种可移植的方式来接收(方便的)$_SERVER['PATH_INFO']变量。

读了一会儿,原来它PATH_INFO起源于 CGI/1.1,我并不总是出现在所有配置中。

获取该变量的最佳(主要是安全方面)方法是什么 -除了手动提取它(安全问题)。

4

6 回答 6

11

好吧,我(几乎)确定,如果不使用$_SERVER超全局键,提供另一种方法来找出PATH_INFO是不可能的,也就是说让我们首先列出我们可能使用的所有 $_SERVER 键:

  • 'PHP_SELF'
  • '请求参数'
  • 'SCRIPT_FILENAME'
  • 'PATH_TRANSLATED'
  • 'SCRIPT_NAME'
  • 'REQUEST_URI'
  • 'PATH_INFO'
  • 'ORIG_PATH_INFO'

我们显然需要忽略最后两个。现在我们应该(事实上我不知道这一点,我只是假设因为你这么说)过滤你提供的链接中存在的所有密钥(顺便说一句,它是离线 ATM),这给我们留下了以下密钥:

  • 'PHP_SELF'
  • 'SCRIPT_FILENAME'
  • 'REQUEST_URI'

关于您对安东尼回答的评论:

你现在只是在玩弄变量。 SCRIPT_FILENAME是 CGI 规范的一部分。如果不可用,它将 PATH_INFO不可用。至于 REQUEST_URI,它是 apache 的 mod_rewrite 特定的。– 里拉努纳

我正在使用 PHP 5.3.0 作为 CGI 运行 LightTPD/1.4.20-1 (Win32),cgi.fix_pathinfo = 1并且$_SERVER['REQUEST_URI']对我来说非常可用,我还记得在没有人使用的时候使用相同的变量,mod_rewrite所以我诚实的猜测是你在这一点上是完全错误的。关于SCRIPT_FILENAME钥匙,我无法测试那台自动取款机。尽管如此,如果我们非常努力地闭上眼睛并相信你是对的,那么我们就只有一个变量:

  • 'PHP_SELF'

我并没有试图在这里苛刻(我仍然相信还有更多的解决方案),但如果PHP_SELF是您希望我们使用的唯一关键(假设对自身没有强加PHP_SELF),则只剩下一个解决方案:

function PATH_INFO()
{
 if (array_key_exists('PATH_INFO', $_SERVER) === true)
 {
  return $_SERVER['PATH_INFO'];
 }

 $whatToUse = basename(__FILE__); // see below

 return substr($_SERVER['PHP_SELF'], strpos($_SERVER['PHP_SELF'], $whatToUse) + strlen($whatToUse));
}

这个函数应该可以工作,但是使用常量可能会出现一些问题__FILE__因为它返回__FILE__声明常量的文件的路径,而不是请求的 PHP 脚本的路径,所以这就是 $whatToUse 存在的原因:你可以将其替换为,'SCRIPT_FILENAME'或者如果您真的相信您所说的话,只需使用'.php'.

您还应该阅读这篇文章,了解为什么不使用PHP_SELF.

如果这对您不起作用,我很抱歉,但我可以想到其他任何事情。

编辑-为您阅读更多内容:

于 2009-12-16T17:09:53.700 回答
2

我认为这是以其他方式获取“path_info”的技巧:

$path_info = str_replace($_SERVER['SCRIPT_NAME'], '', $_SERVER['PHP_SELF']);

例如,访问如下 URL:http://somehost.com/index.php/some/path/here,其值为$path_info"/some/path/here"

它在 Windows 和 linux 上运行的各种 apache 服务器中对我有用,但我不能 100% 确定它是否“安全”和“便携”,显然我没有在“所有”服务器配置中测试它,但似乎可以工作...

于 2011-04-11T17:25:06.717 回答
1
function getPathInfo() {
    if (isset($_SERVER['PATH_INFO'])) {
        return $_SERVER['PATH_INFO'];
    }  
    $scriptname = preg_quote($_SERVER["SCRIPT_NAME"], '/');
    $pathinfo = preg_replace("/^$scriptname/", "", $_SERVER["PHP_SELF"]);
    return $pathinfo;
}

编辑:没有 SCRIPT_NAME,并假设你有 DOCUMENT_ROOT(或者可以自己定义/发现它)并假设你有 SCRIPT_FILENAME,那么:

function getPathInfo() {
    if (isset($_SERVER['PATH_INFO'])) {
        return $_SERVER['PATH_INFO'];
    }  
    $docroot = preg_quote($_SERVER["DOCUMENT_ROOT"], "/");
    $scriptname = preg_replace("/^$docroot/", "", $_SERVER["SCRIPT_FILENAME"]);
    $scriptname = preg_quote($scriptname, "/");
    $pathinfo = preg_replace("/^$scriptname/", "", $_SERVER["PHP_SELF"]);
    return $pathinfo;
}

还有@Anthony(没有足够的代表发表评论,抱歉):使用 str_replace() 将匹配字符串中的任何位置。它不能保证有效,您只想在开始时匹配它。此外,您仅使用 1 个斜线(通过 strrpos)来确定 SCRIPT_NAME 的方法仅在脚本位于根目录下时才有效,这就是为什么最好将 script_filename 与 docroot 进行比较。

于 2009-12-15T05:02:12.323 回答
1

这取决于“便携”和“安全”的定义。

让我看看我是否理解:

1) 你对 CLI 不感兴趣:

  • 你提到了 PHP/CGI
  • PATH_INFO 是一段 URL;因此,只有在从 URL 访问脚本(即从 HTTP 连接,通常由浏览器请求)时讨论 PATH_INFO 才有意义

2)您希望在所有操作系统 + HTTP 服务器 + PHP 组合中都有 PATH_INFO:

  • 操作系统可能是 Windows、Linux 等
  • HTTP 服务器可能是 Apache 1、Apache 2、NginX、Lighttpd 等。
  • PHP 可能是版本 4、5、6 或任何版本

嗯... PHP_INFO,在 $_SERVER 数组中,由 PHP 提供给仅在特定条件下执行的脚本,具体取决于上述软件。它并不总是可用的。整个 $_SERVER 数组也是如此!

简而言之:“ $_SERVER 取决于服务器”...所以便携式解决方案不能在 $_SERVER 上中继...(仅举一个例子:我们有一个在 NginX 上设置 PHP/CGI $_SERVER 变量的教程HTTP 服务器位于 kbeezie.com/view/php-self-path-nginx/)

3)尽管上面提到了,但值得一提的是,如果我们以某种方式将请求的完整 URL作为字符串提供,则可以通过应用正则表达式和其他 PHP 字符串函数从中安全地获取 PATH_INFO(也验证输入字符串作为有效的 URI)。

因此,只要我们有URL 字符串……那么是的,我们有一种可移植且安全的方法来从中确定 PATH_INFO。


现在,我们有两个明确且重点突出的实施问题:

  1. 如何获取网址?
  2. 如何从 URL 中获取 PATH_INFO?

在几种可能性中,这是一种可能的方法:

如何获取网址?

1) 凭借您对每个 HTTP 服务器 + 操作系统 + PHP 版本组合的深入而全面的了解,检查并尝试从 $_SERVER 数组中获取 URL 的每种可能性(验证 'PHP_SELF'、'QUERY_STRING'、'SCRIPT_FILENAME'、'PATH_TRANSLATED' , 'SCRIPT_NAME', 'REQUEST_URI', 'PATH_INFO', 'ORIG_PATH_INFO', 'HTTP_HOST', 'DOCUMENT_ROOT' 或其他)

2) 如果上一步失败,则使 PHP 脚本返回一个 javascript 代码,该代码将“document.URL”信息返回。(转移到客户端的可移植性问题。)

如何从 URL 中获取 PATH_INFO?

此处链接的此代码执行此操作。

这是我的拙见和解决问题的方法。

你怎么看?

于 2010-05-29T12:45:41.630 回答
0

在发布之前我没有看到评论或链接。根据上面引用的页面作为 CGI 派生变量给出的内容,这可能会起作用:

function getPathInfo() {
    if (isset($_SERVER['PATH_INFO'])) {
        return $_SERVER['PATH_INFO'];
    }  

    $script_filename = $_SERVER["SCRIPT_FILENAME"];
    $script_name_start = strrpos($script_filename, "/");
    $script_name = substr($script_filename, $script_name_start);

    //With the above you should have the plain file name of script without path        

    $script_uri = $_SERVER["REQUEST_URI"];
    $script_name_length = strlen($script_name);
    $path_start = $script_name_length + strpos($script_name, $script_uri);

    //You now have the position of where the script name ends in REQUEST_URI

    $pathinfo = substr($script_uri, $path_start);
    return $pathinfo;
}
于 2009-12-15T05:32:29.413 回答
-1

你可以试试

$_ENV['PATH_INFO']; or
getenv('PATH_INFO']; 
于 2009-12-10T21:17:50.550 回答