PHP添加查询字符串(如果它不存在)

时间:2015-03-02 17:01:55

标签: php

在开始之前,我对PHP完全不熟悉。这可能是一个愚蠢的错误,我可能以最糟糕的方式做到这一点。

我有这段代码:

<?php
    if (!isset($_GET['p'])) {
    $url .= '?p=home';
    header('Location:' . $url);
    exit;
}
elseif (!isset($_GET['sp'])) {
    header("Location: ".$_SERVER['REQUEST_URI'].'&sp=index.php';);
die();
}
include('/Page/' . htmlspecialchars($_GET["p"]) . '/' . htmlspecialchars($_GET["sp"]));
?>

基本上,网址格式为www.example.com/?p=PAGE&sp=SUBPAGE.php

此内部格式为/Page/PAGE/SUBPAGE.php

原因:

  • 每个帖子&#39;将拥有它自己的文件夹以获取它的资源。 (?p=)然后,他们可以在文件夹中放置任何内容,并使用SUBPAGE (&sp=)链接到该文件夹​​。

  • 这可以保持所有内容的整理,并阻止任何内部链接到/page/区域以外的任何地方。

出了什么问题:

  • 如果没有Page(p)集,我需要添加?p=home作为默认值,如果它们没有SubPage(sp)集,我需要默认添加&sp=index.php

  • 如果没有Page,则SubPage将重置为默认值。

  • 如果您在www.example.com/?p=blog页面上,则会在不删除页面的情况下添加子页面(?p=blog?p=blog&sp=index.php

  • 但是,如果没有页面,则子页面将重置为默认值。

问题:

我怎么能这样做?

提前谢谢你。

2 个答案:

答案 0 :(得分:1)

我会以不同的方式处理这种情况。

为页面和内页设置一些变量,使用默认值,只有在$_GET参数设置

时才重新分配它们
$page = 'home';
$inner_page = 'index.php';

if( isset( $_GET['p'] ) )
{
    $page = htmlspecialchars( $_GET['p'] );
}

if( isset( $_GET['sp'] ) )
{
    $inner_page = htmlspecialchars( $_GET['sp'] );
}

include $_SERVER['DOCUMENT_ROOT'] . '/Page/' . $page . '/' . $inner_page;

我也添加了$_SERVER['DOCUMENT_ROOT'],因为如果您使用/Page,那么它是绝对路径,可能不是您所期望的那样,因此预先$_SERVER['DOCUMENT_ROOT']确保您正在查看您的网络目录中的路径。

还有其他值得注意的事情;不要假设数据是好的,人们可以尝试操纵包含的文件。

http://your.domain/index.php?p=../../../../../&sp=passwd

因此,首先要尝试清理数据是值得的。

答案 1 :(得分:0)

您当前的代码存在严重的安全漏洞。

编写应用时最重要的规则之一,永远不要信任来自客户端的数据。总是假设,他们会向您发送错误或虚假的数据。

我建议您创建一个配置文件,定义允许的路由。

通过执行以下行,您只允许任何人访问您的网络服务器可读的任何文件。

include('/Page/' . htmlspecialchars($_GET["p"]) . '/' . htmlspecialchars($_GET["sp"]));

如果您为$ _GET ['p']发送了一个有效值,那么会发生什么?$ _GET ['sp']:

"/../../../../../../../../../../../etc/apache2/httpd.conf"

在此示例中,它将输出您的apache配置文件(假设这是正确的路径,如果不是黑客可以继续尝试路径,直到找到它。)

为避免这种情况,您有两种解决方案。

1#快速修复 - 您可以消毒&amp;过滤$ _GET ['p']和$ _GET ['sp']以确保您没有得到'/../'。请务必至少添加file_exists,以避免收到不需要的警告消息。

2#更优雅的修复 - 您可以创建一个包含您正在接受的路由的配置文件。如果您使用的是框架,那么您很可能拥有可以使用的路由类或路由模块。否则,如果您想要实现自己的基本路由机制,您可以做一些像您的情况一样简单的事情:

<?php
/**
 * Defines the different routes for the web app
 * @file : config.routes.php
 */
return array(
    'page1' => array(
         'index.php',
         'subpage2.php',
         'subpage3.php',
    ),
);

然后,你要检查你的代码是否允许$ _GET ['p']和$ _GET ['sp']值。

<?php
// Load config file containing allowed routes
$allowedRoutes = require(__DIR__ . '/config.routes.php');

$defaultPage = 'home';
$defaultSubPage = 'index.php';

$page = isset($_GET['p']) ? $_GET['p'] : defaultPage;
$subPage = isset($_GET['sp']) ? $_GET['sp'] : $defaultSubPage;

// If it is an invalid route, then reset values to default
if (!isset($allowedRoutes[$page][$subPage])) 
{
    $page = $defaultPage;
    $subPage = $defaultSubPage;
}

include $_SERVER['DOCUMENT_ROOT'] . '/Page/' . $page . '/' . $subPage;