阻止直接访问 PHP 页面

Prevent direct access to a PHP page

提问人:syaz 提问时间:10/9/2008 最后编辑:syaz 更新时间:2/3/2014 访问量:17370

问:

如何防止我的用户直接访问仅用于 ajax 调用的页面?

在 ajax 调用期间传递密钥似乎是一种解决方案,而没有密钥的访问将不会被处理。但是制造钥匙也很容易,不是吗?视图源的诅咒...

p/s:使用 Apache 作为 Web 服务器。

编辑:为了回答原因,我的索引.php中有jQuery ui选项卡,在这些选项卡中是带有脚本的表单,如果直接访问它们,则无法正常工作。为什么用户想要这样做,我不知道,我只是认为通过阻止在没有验证脚本的情况下直接访问表单,我会更加用户友好。

php ajax apache

评论

2赞 Kirk Strauser 10/9/2008
在这种情况下,不要担心用户友好性。事实上,我想说的是,你最好早点失败,而不是试图让它变得愉快。例如,假设您将其重定向到非 AJAX 访问的索引 .php。结果:保证有人会为 AJAX 脚本添加书签,因为它会将它们带到您的主页。

答:

34赞 Paige Ruten 10/9/2008 #1

无法保证他们通过 AJAX 访问它。直接访问和 AJAX 访问都来自客户端,因此很容易被伪造。

你为什么要这样做?

如果是因为PHP代码不是很安全,那就让PHP代码更安全。(例如,如果 AJAX 将用户 ID 传递给 PHP 文件,请在 PHP 文件中编写代码以确保该用户 ID 是正确的。

评论

4赞 Kirk Strauser 10/9/2008
没什么可说的了。永远不要相信客户发给你的东西。由于 AJAX 方法旨在将内容返回给浏览器,因此请确保在后端只能返回授权数据。
0赞 Jacob Krall 10/9/2008
我唯一的遗憾是,我只有一票可以回答这个答案。
4赞 scronide 10/9/2008
我唯一的遗憾是我有骨头——它是。
1赞 Kzqai 9/25/2009
由于他只想要用户友好性,因此只要安全性与它无关,对 XMLHttpRequest 的检查似乎是一个很好的解决方案。
8赞 Draemon 10/9/2008 #2

听起来你可能做错了事情。AJAX 调用就像标准页面请求一样,只是按照约定,响应不会显示给用户。

但是,它仍然是一个客户端请求,因此您必须很高兴客户端能够看到响应。以这种方式使用“密钥”混淆访问只会使事情复杂化。

实际上,我想说的是,视图源的“诅咒”是通过隐蔽性来对抗安全性的一个小武器。

那么,你为什么要这样做呢?

评论

0赞 J.C. Inacio 9/25/2009
我喜欢“通过默默无闻来对抗安全的小武器”。 部分 - 介意我是否引用它?:)
4赞 Cristian Vat 10/9/2008 #3

如果浏览器将通过正常请求或ajax调用您的页面,那么有人可以手动调用它。就服务器-客户端通信而言,普通请求和 ajax 请求之间确实没有明确定义的区别。

常见的情况是将一个标头传递给服务器,上面写着“此请求是由ajax完成的”。如果您使用的是 Prototype,它会自动将 http 标头“X-Requested-With”设置为“XMLHttpRequest”,以及一些其他标头,包括原型版本。(详见 http://www.prototypejs.org/api/ajax/options“requestHeaders”)

添加:如果您使用的是其他 AJAX 库,您可以添加自己的标头。这对于了解服务器端的请求类型以及避免在浏览器中请求 ajax 页面的简单情况非常有用。它不会保护您的请求免受所有人的侵害,因为您不能。

0赞 Eric Tuttleman 10/9/2008 #4

不确定这一点,但可能会检查引荐来源网址标题?我认为如果有人手动输入您的 URL,它就不会有引荐来源标头,而 AJAX 调用有(至少在我刚刚在系统上进行的快速测试中)。

不过,这是一种糟糕的检查方式。由于很多原因,Referrer 可能是空白的。你是想阻止人们把你的网络服务当作公共服务来使用吗?

阅读编辑注释后,如果表单将通过ajax调用加载,则可以检查window.location以查看url是否是ajax表单的url。如果是,请通过 document.location 转到正确的页面

评论

0赞 Alex Weinstein 10/9/2008
伪造引荐来源网址标题非常容易。
0赞 Eric Tuttleman 10/9/2008
@Alex Right,这将是“由于很多原因可能为空白”声明中包含的原因之一。此页面上的答案可能是伪造的,因为它们都是客户端输入法 - 客户端发送到服务器的数据。将本页上的每个答案标记为否定。
24赞 Eran Galperin 10/9/2008 #5

正如其他人所说,Ajax 请求可以通过创建正确的标头来模拟。 如果要进行基本检查以查看请求是否为 Ajax 请求,可以使用:

 if($_SERVER['HTTP_X_REQUESTED_WITH'] == 'XMLHttpRequest') {
     //Request identified as ajax request
 }

但是,您绝不应将安全性建立在此检查的基础上。如果您需要,它将消除对页面的直接访问。

评论

1赞 syaz 10/9/2008
我得到未定义的索引:HTTP_X_REQUESTED_WITH。你的意思是我必须自己分配这个值吗?
0赞 Eran Galperin 10/9/2008
你用什么框架来做 Ajax requets?(我希望你没有使用自制的解决方案......
0赞 Eran Galperin 10/9/2008
而且,该参数仅在 Ajax 请求中可用。如果您不希望出现未定义的索引错误,则可能需要添加 isset() 检查
3赞 Draemon 10/10/2008
Syaz,这不是基本的安全。正如 Eran 正确地说的那样 - “你永远不应该把你的安全性建立在这个检查上” 这很容易伪造(我敢肯定 wget 或许多 firefox 插件可以非常简单地做到这一点)你还没有说为什么你可能想要这个 - 有什么可以保护的?
1赞 syaz 10/10/2008
我已经编辑了我的第一篇文章,以说明我想要实现的目标——用户友好性。就这么简单。;)
0赞 Kelly 8/15/2009 #6

这对于保护某些东西绝对没有用。但我认为,如果你想让一个 php 页面生成整个页面,如果该页面不是由 ajax 请求的,而只生成使用 ajax 时返回的您需要的部分,这可能会有用。这将允许你使你的网站对ajax不友好,所以如果说他们点击了一个链接,它应该加载一个评论框,但他们没有ajax,它仍然会将它们发送到页面,然后生成为一个显示评论的整个页面。

1赞 Kzqai 9/25/2009 #7

COOKIES不安全...试试 _SESSION 美元。这几乎是您实际上可以依赖的少数几件事之一,这些跨页面不能被欺骗。因为,当然,它基本上永远不会离开你的控制。

0赞 Antony Carthy 3/26/2010 #8

通过 index.php 传递直接请求,通过 ajax.php 传递 ajax 请求,然后不让用户直接浏览到任何其他源文件 - 确保 index.php 和 ajax.php 具有适当的逻辑来包含它们需要的代码。

1赞 foxybagga 2/18/2011 #9

谢谢,虽然我用

define('IS_AJAX', isset($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest');

if(IS_AJAX) {
    //Request identified as ajax request
}

干杯!

0赞 Jeroenv3 2/3/2014 #10

在调用脚本的 javascript 文件中:

var url = "http://website.com/ajax.php?say=hello+world";
xmlHttp.open("GET", url, true);
xmlHttp.setRequestHeader('X-Requested-With', 'XMLHttpRequest');

然后在 PHP 文件 ajax.php 中:

if($_SERVER['HTTP_X_REQUESTED_WITH'] != "XMLHttpRequest") {
    header("Location: http://website.com");
    die();
}

极客仍然可以通过伪造标头来调用ajax.php脚本,但我的脚本的其余部分需要会话,因此当未检测到有效会话时,执行结束。我需要它才能工作,以便将具有过期 hybridauth 会话的人重定向到主站点以便再次登录,因为他们最终被重定向到 ajax 脚本。