17

这里已经发布了几个关于在特殊情况下返回 404 而不是 403 的问题(例如,.ht* 文件或某个目录),但我不知道如何简单地替换所有403 响应(“好的,它存在,但您仍然必须找到一种方法进入“)与 404(“抱歉,从未听说过”)。我希望有一个简单的解决方案,不需要更新 .htaccess 的正则表达式或其他位以匹配站点更改,只需一个简单的指令:“每当您决定返回 403 时,就返回 404”适用到整个站点,无论配置更改如何。

然后,如果顶级 .htaccess 包含“Options -Indexes”,并且任何给定目录不包含 index.html(或等效),那么裸目录 URL 将返回 404,但如果我将 index.html 添加到该目录,相同的裸目录 URL 将返回 index.html,无需对任何 .htaccess 文件进行更新。

我什至不在乎,如果我曾经为目录输入密码,错误的密码是否会返回 404(因为 404 -> 403 映射)。在这种情况下,我不会通过返回 404 来隐藏任何内容,但这也不会造成任何伤害。但是,如果有一种方法可以撤消针对特殊情况的一般 403->404 映射(而不是针对特殊情况执行此操作),那可能会更有用。

当然,如果我忽略了什么,请让我直截了当。

编辑:德拉特。我试图在这里写一个高质量的问题,但我在第二段中对“Options -Indexes”行为的描述结果是错误的。没有该行,如果目录中存在裸目录 URL,则会显示“index.html”;否则,它会显示目录的内容。(如果 index.html 存在,则 /dir 到 /dir/index.html 的转发是 Web 主机的默认设置,除非我弄错了。)添加“Options -Indexes”行会阻止它在公共场合晾晒我的衣服(返回 403,而不是 404,但仍然比公开目录内容更好),但现在即使 index.html 存在,裸目录 URL 也会返回 403。

我希望裸目录 URL“mysite.com/mydir”如果存在则显示 /mydir/index.html,如果不存在则显示“404”,但显然它不仅仅是用 404 替换 403。

4

5 回答 5

13

要在此处完成更好的答案之一(如@WebChemist 和@JennyD 所述),解决此问题的一个好方法是404 Not Found从您用于处理403错误的文档中返回。就我个人而言,我会执行以下操作:

.htaccess在网络根目录(相关摘录):

ErrorDocument 400 /http-errors.php
ErrorDocument 403 /http-errors.php
ErrorDocument 404 /http-errors.php

http-errors.php在 Web 根目录中(精简的工作示例):

<?php

$status = $_SERVER['REDIRECT_STATUS'];
// If it's a 403, just bump it up to a 404
if ( $status == 403 ) $status++;

$codes = array(
  400 => array( '400 Bad Request', 'The request cannot be fulfilled due to...' ),
  404 => array( '404 Not Found', 'The resource you requested was not found...' ),
  500 => array( '500 Internal Server Error', 'The request was unsuccessful...' )
);

$title = $codes[$status][0];
$message = $codes[$status][1];

header( $_SERVER['SERVER_PROTOCOL'] . ' ' . $title );
echo "<h1>$title</h1>\n<p>$message</p>";
于 2013-05-14T21:34:49.750 回答
3

你可以很容易地做一个假的 403 -> 404

ErrorDocument 403 /404.php

其中 404.php 是您格式化的 404 响应页面,但仍会在响应标头中返回 403。如果要返回 404 标头,可以使用返回 404 代码的标头重定向制作 403 页面,但重定向可能仍然可见....

不确定您是否可以用纯 .htaccess 进行全面的 403->404 替换

编辑:

玩了一下,您可以尝试 2 种纯 .htaccess 方法:

1)使任何以斜杠结尾的网址重定向到索引页面,例如:

RewriteRule ^(.*)/$ /$1/index.php [NC,L]

因此,如果您确实有索引页面,它将显示,但如果没有,它将在缺少索引页面请求时显示 404。如果您省略 [R],则该 url 仍将显示为 / 非 index.php 规范的 SEO 友好 url :) 不能说这不会在其他地方造成问题..

2)

在重写规则中,您可以使用 r=404 返回 404 代码。

RewriteRule ^(.*)/$ - [R=404, NC,L]

但是 RewriteCond %{REQUEST_FILENAME} !-fRewriteCond %{REQUEST_FILENAME} -d

没有帮助,这意味着即使存在索引页面,所有尾随斜杠也会 404。您可以通过在其他 RewriteCond 规则中指定要保护(或忽略)的文件夹来解决此问题,但这并不完全是“自动的”,因为您必须添加 RewriteCond 规则,因为更多文件夹被添加到保护|忽略

于 2012-05-09T04:47:33.467 回答
3

这是我的 .htaccess 文件中的一个片段,该文件位于我已阻止但允许从 LAN 机器访问的目录中。每次都返回 404 错误!!

# Turn rewrite engine on
RewriteEngine on
RewriteOptions Inherit

# Make it for a specific directory
# RewriteBase /phpMyAdmin 

# Block everyone except me
RewriteCond %{REMOTE_HOST} !^192.168.2
RewriteRule .? - [R=404,L]
于 2013-01-10T16:57:39.070 回答
2

据我所知,没有这样简单的指令。它仍然是可能的,但它比你可能想要的要复杂一些。

您可以使用 ErrorDocument 指令将 403 响应设置为脚本,然后让该脚本以 404 响应而不是 403 响应来响应。apache.org上有一些提示可能会有所帮助

于 2012-05-09T04:44:45.197 回答
-1

即使可能没有全面的方法来获取 403 错误来报告 404 错误,但仍有希望。

我怀疑您真正想要的是确保 /~root (以及任何其他现有的非 HTTP 用户)不会返回 403,而是返回 404。

Apache 中的 UserDir 指令按设计返回 403。我认为目前无法改变。但是 - 'UserDir' 指令可以在同一个 Apache 文件中多次使用,如下所示:

UserDir public_html UserDir 禁用 root someuser1 someuser1

该配置将允许使用 UserDir,但也会向所有试图在您的系统周围嗅探的人报告珍贵的 404 响应标头。

我从以下链接中找到了这个提示:

http://www.if-not-true-then-false.com/2010/enable-apache-userdir-with-selinux-on-fedora-centos-red-hat-rhel/

我自己在 Apache 2.2.15 下的 RHEL 6.3 中对其进行了测试,并且它可以工作——即使在使用 curl 之类的东西进行测试时也是如此。我也在寻找解决方案。终于找到了我可以使用的东西!

于 2012-12-20T17:59:33.937 回答