我正在进行设置,其中的网址将是:
http://example.com/index.php?page=about
实际上,他们会从更简单的URL重写。 index.php
将使用以下代码包含其他页面:
if ( isset( $_GET['page'] ) )
{
$page = $_SERVER['DOCUMENT_ROOT'] . '/pages/' . $_GET['page'] . '.php';
if ( is_file( $page ) )
include $page;
else
echo 'That page doesn\'t exist.';
}
假设页面文件夹中的所有内容都非常安全,那么此代码是否安全?我已经防范了众所周知的目录黑客,即使用page=../../.passwd
。还有什么我应该留意的吗?
答案 0 :(得分:9)
最好转换它
$page_name = $_GET['page'];
switch($page_name) {
case 'about':
$page = $_SERVER['DOCUMENT_ROOT'] . '/pages/about.php';
break;
case 'home': //fall through to default
case default:
$page = $_SERVER['DOCUMENT_ROOT'] . '/pages/home.php';
}
include $page;
这样就没有任何注射问题。
修改
另一个解决方案是设置一个专门处理页面名称转换为地址的类。
class Page {
static private $pages = array ("about", "home");
const DEFAULT_PAGE = "home";
static public function includePage($page_name) {
if (!in_array($page_name, self::$pages)) {
$page_name = self::DEFAULT_PAGE;
}
include ($_SERVER['DOCUMENT_ROOT'] . '/pages/'.$page_name.'.php';);
}
}
通过这种方式,这一切都在一个类中进行管理,未来的更改更容易进行,而无需深入了解其他代码
以上编辑以反映请求。
答案 1 :(得分:4)
您的代码没问题,除非您在使用前验证参数:
if(!preg_match("~^\w+$~", $_GET['page']))
die("page id must be alphanumeric!");
我不推荐“切换”方法,因为它降低了灵活性,这是使用动态包含的全部要点。
答案 2 :(得分:1)
您也可以切换到像CodeIgniter这样的框架,它将为您完成所有这些并迫使您采用一些始终是好事的编码标准。
答案 3 :(得分:1)
一种非常安全的方法是首先构建目录内容列表,然后将用户输入与该列表匹配,使用列表中的值包含< / strong>即可。有些东西:
$sdir = $_SERVER['DOCUMENT_ROOT'].'/pages/';
$targetfile = $_GET['page'].'.php';
$filenames = scandir($sdir); // returns an array of directory contents
foreach ($files as $filename) {
if (($filename[0] != '.')
&& ($filename == $targetfile)
&& (is_file($sdir.$filename)) {
include $sdir.$filename;
break;
}
}
或者您可以通过以下方式完成:
$targetfile = $_GET['page'].'.php';
$sdir = $_SERVER['DOCUMENT_ROOT'].'/pages/';
$filenames = scandir($sdir);
if (in_array($targetfile,$filenames)) {
include $sdir.$filename;
}
但在后一种情况下,您必须非常确定才能获得正确的检查条件,并使用regex check suggested in another answer。在第一种情况下,您只包含从目录内容构建的列表,因此即使用户设法通过您的支票获得一些奇怪的输入,它也是安全的。
答案 4 :(得分:0)
处理任意数量的页面时,最好确保您拥有SEO友好的文件名。我会推荐带有连字符或下划线的字母数字文件名:
define(DOCROOT, $_SERVER['DOCUMENT_ROOT']);
// assume you do not include file extensions in $_GET['page']
$page = trim(preg_replace('~[^\\pL\d]+~u', '-', $_GET['page']), '-');
if (is_file($page)) {
include DOCROOT . $page;
}