首页 > 解决方案 > 如何防止直接访问php页面但重定向时可以访问

问题描述

我想阻止直接访问我的错误页面,404.php但我希望在从其他页面重定向时可以访问该页面。

就像我的网站名称一样example.com/index.php,如果任何用户以任何方式输入错误,example.com/ind.php它将被重定向到我的文件404.php中,以便在我.htaccess使用过的文件中执行此操作。

另外,假设在我的index.php文件中,当单击任何产品时,我正在显示一些产品,它将我product.php?pid=4带到pid包含.idid!=4404.php

一切都很好,但是如果我访问example.com/404.php它会向我显示页面,我只希望用户何时直接使用example.com/404.php它将重定向到index.php文件。而已。

# enable url rewriting
RewriteEngine On 
ErrorDocument 404 http://localhost/news_21_off/404.php

索引.php

$sql = "select * from products";
$res = mysqli_query($co,$sql);
$rs = mysqli_fetch_assoc($res);

$res_id = $rs['id'];

<a href="products.php?pid=<?php echo $res_id; ?>">Product</a>

产品.php


if(isset($_GET['pid']) && $_GET['pid']=='4'){
echo 'correct';
}else{

header('location:404.php');
}

404.php

<h1>My 404 page</h1>

到目前为止,我还没有找到这样做的方法。

标签: php.htaccessmod-rewrite

解决方案


到此为止的一切工作都很好...

其实我觉得不是...

...防止直接访问 php 页面,但可以在重定向时访问

这不仅仅是任何 PHP 页面。这是您的 404“未找到”错误文档。

首先,您不应该在外部 3xx 重定向到您的错误文档。错误文档应该在同一个请求中提供(“内部子请求”)。这是您的问题的根本原因。

重定向请求是一个完全独立的请求,与“直接请求”几乎没有区别,这自然会使可靠地阻止直接请求“不可能”。但是,您真的需要阻止对 404 错误文档的“直接请求”吗?(见下文...)

ErrorDocument 404 http://localhost/news_21_off/404.php

通过在指令中指定一个绝对 URL(即带有方案 + 主机名)ErrorDocument,Apache 将触发 302 外部重定向到指定的 URL。除非您在 PHP 代码中手动发送 404“未找到”状态(没有证据表明这里)。

仅仅因为 Apache 允许您“重定向”到错误文档,并不意味着您应该这样做。如Apache 文档中所述:

请注意,当您指定一个ErrorDocument指向远程 URL(即前面带有 http 等方法的任何内容)时,Apache HTTP Server 将向客户端发送重定向以告诉它在哪里可以找到文档,即使文档最终位于同一台服务器上。这有几个含义,最重要的是客户端不会收到原始错误状态代码,而是会收到重定向状态代码。这反过来又会混淆网络机器人和其他尝试使用状态代码来确定 URL 是否有效的客户端。

此外,通常与触发 404 的 URL 相关的所有有用的 PHP 超全局变量(从 Apache 传递)都将丢失(例如$_SERVER['REDIRECT_STATUS']$_SERVER['REDIRECT_URL']等),因为如上所述,重定向请求是一个完全独立的请求。

99.99% 的情况下,您应该在ErrorDocument指令中使用根相对 URL 路径,以便 Apache 触发错误文档的内部子请求,例如:

ErrorDocument 404 /news_21_off/404.php
header('location:404.php');

同样,您也不应该“重定向”到 PHP 代码中的错误文档。

在 PHP 中,有多种方法可以解决这个问题。您可以简单地include()在您希望为 404 提供服务的代码中的点处提供错误文档。

例如,在您的products.php脚本中:

<?php
$pid = $_GET['pid'] ?? null;
if ($pid == '4') {
    echo 'correct';
} else {
    // 404 Not Found
    include($_SERVER['DOCUMENT_ROOT'].'/news_21_off/404.php');
    exit();
}

但是,上面不会向客户端发送 404 HTTP 状态代码。在您的 PHP 404 错误文档中,您应该设置 HTTP 状态以确保 PHP 发送 404 状态以及何时/如果用户直接访问该文档。

例如,在您的404.php脚本中:

<?php
http_response_code(404);
?>
<h1>My 404 page</h1>

顺便说一句,在 PHP 脚本中设置 HTTP 状态代码将覆盖 Apache 在提供错误文档时可能设置的任何状态。

现在,回到你最初的问题......

我想阻止直接访问我的错误页面 404.php

为什么?

实施上述更改后,如果用户确实“直接访问”您的 404 错误文档,他们只会收到 404 并看到相同的响应,就好像他们请求了任何其他不存在的文档一样。

因此,除非您有特定要求,否则您无需在这里做任何其他事情。


推荐阅读