我正在寻找一种可移植的方式来接收(方便的)$_SERVER['PATH_INFO']
变量。
读了一会儿,原来它PATH_INFO
起源于 CGI/1.1,我并不总是出现在所有配置中。
获取该变量的最佳(主要是安全方面)方法是什么 -除了手动提取它(安全问题)。
好吧,我(几乎)确定,如果不使用$_SERVER
超全局键,提供另一种方法来找出PATH_INFO
是不可能的,也就是说让我们首先列出我们可能使用的所有 $_SERVER 键:
我们显然需要忽略最后两个。现在我们应该(事实上我不知道这一点,我只是假设因为你这么说)过滤你提供的链接中存在的所有密钥(顺便说一句,它是离线 ATM),这给我们留下了以下密钥:
关于您对安东尼回答的评论:
你现在只是在玩弄变量。
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
),则只剩下一个解决方案:
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'
.
如果这对您不起作用,我很抱歉,但我可以想到其他任何事情。
编辑-为您阅读更多内容:
REQUEST_URI
是 Apache 特定的?)PHP_SELF
对PATH_INFO
对SCRIPT_NAME
对REQUEST_URI
我认为这是以其他方式获取“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% 确定它是否“安全”和“便携”,显然我没有在“所有”服务器配置中测试它,但似乎可以工作...
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 进行比较。
这取决于“便携”和“安全”的定义。
让我看看我是否理解:
1) 你对 CLI 不感兴趣:
2)您希望在所有操作系统 + HTTP 服务器 + PHP 组合中都有 PATH_INFO:
嗯... 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) 凭借您对每个 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”信息返回。(转移到客户端的可移植性问题。)
这是我的拙见和解决问题的方法。
你怎么看?
在发布之前我没有看到评论或链接。根据上面引用的页面作为 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;
}
你可以试试
$_ENV['PATH_INFO']; or
getenv('PATH_INFO'];