防止直接访问由ajax函数调用的文件[重复]

Posted

技术标签:

【中文标题】防止直接访问由ajax函数调用的文件[重复]【英文标题】:Prevent Direct Access To File Called By ajax Function [duplicate] 【发布时间】:2010-12-17 21:57:02 【问题描述】:

我正在像这样从 ajax 调用 php 代码:

ajaxRequest.open("GET", "func.php" + queryString, true);

由于这是一个获取请求,任何人都可以通过简单地检查标头来查看它。传递的数据不敏感,但可能会被滥用,因为获取参数名称也很简单。

如何防止直接访问 http://mysite/func.php 却允许我的 ajax 页面访问它?

我也尝试了posted here 的解决方案,但它对我不起作用 - 总是收到“未预先允许直接访问”消息。

【问题讨论】:

所以您基本上希望您的脚本可以通过 AJAX 访问,但如果我输入 URI 则不是? 您发布的链接中描述的 .htaccess 是否有不能使用的原因? Zarembisty:在这种情况下,.htaccess 不是一个选项。即使他们使用的是 apache。该页面必须对 http 请求可用,因为它必须通过 AJAX 可用。如果你阻止它,你也会阻止 AJAX @Palantir - 当然 .htaccess 是一个选项 - 您可以阻止除您自己的服务器之外的所有内容的访问;显然,这不是 IIS 的选择,但对于 apache,它是一个可行的替代方案 @themerlinproject - 确实是旧线程。我不知道当我发布这些 cmets 时脑子里在想什么,但我完全同意如果要从客户端使用 AJAX,.htaccess 不是一个选项。 【参考方案1】:

我会质疑您为什么如此确信没有人应该能够直接访问该文件。你的第一个动作真的应该是假设人们可以直接访问该页面并针对这种可能性采取行动。如果您仍然确信要关闭对该文件的访问,那么您应该知道您不能信任 $_SERVER 变量,因为 $_SERVER 的来源可能难以确定,并且标头的值可能被欺骗。在我做的一些测试中,我发现这些标头($_SERVER['HTTP_X_REQUESTED_WITH'] & $_SERVER['HTTP_X_REQUESTED_WITH'])也不可靠。

【讨论】:

因为机器人和黑客、爬虫、ddosers,互联网是一个令人讨厌的地方,你给他们一些东西,人们会试图用它来摧毁你。【参考方案2】:

我有一个 Edoardo 解决方案的简化版本。

    网页 A 创建一个随机字符串 [token],并将具有该名称的文件保存在磁盘上的受保护文件夹中(例如,在 Apache 上使用 .htaccess 和 Deny from all)。

    页面 A 将 [token] 与 AJAX 请求一起传递给脚本 B(在 OP 的 queryString 中)。

    脚本 B 检查 [token] 文件名是否存在,如果存在,则继续执行脚本的其余部分,否则退出。

    您还需要设置一些清理脚本,例如。使用 Cron,因此旧令牌不会在磁盘上累积。

用脚本B马上删除[token]文件也不错,限制多次请求。

我不认为 HTTP 标头检查是必要的,因为它很容易被欺骗。

【讨论】:

【参考方案3】:

我尝试了很多建议,但没有人解决问题。最后我保护了 php 目标文件的参数,这是限制直接访问 php 文件的唯一方法。 ** 通过.htaccess 放置php 文件并设置限制导致主html 页面中的Ajax 连接失败。

【讨论】:

【参考方案4】:

我试过了

1) 在主 php 文件(从中发送 ajax 请求)中创建具有一些随机值的会话,例如 $_SESSION['random_value'] = 'code_that_creates_something_random'; 必须确定,该会话是在 $.post 之上创建的。

2) 然后

$.post( "process_request.php", 
 
input_data:$(':input').serializeArray(),
random_value_to_check:'<?php echo htmlspecialchars( $_SESSION['random value'], ENT_QUOTES, "UTF-8"); ?>' 
, function(result_of_processing) 
//do something with result (if necessary)
);

3) 和process_request.php

if( isset($_POST['random_value_to_check']) and 
trim($_POST['random_value_to_check']) == trim($_SESSION['random value']) )
//do what necessary

在我定义会话之前,然后使用会话值隐藏输入字段,然后使用 ajax 发送隐藏输入字段的值。但后来决定隐藏输入字段没有必要,因为没有它可以发送

【讨论】:

【参考方案5】:

我解决了这个问题,准备了一个做三件事的检查函数

    检查引用者 $_SERVER['HTTP_REFERER']; 检查 http x 请求 $_SERVER['HTTP_X_REQUESTED_WITH']; 通过桥接文件检查来源

如果三个都通过了,你就可以看到ajax调用的php文件,如果只有一个失败,你就看不到它

第 1 点和第 2 点已经解释过了,桥接文件解决方案是这样工作的:

桥接文件

想象以下场景:

通过 ajax B.php 调用 A.php 页面并且您希望阻止直接访问 B.php

1) A.php 页面加载时会生成复杂的随机码 2) 代码被复制到文件 C.txt 中,不能直接从 网络(httpd 安全)

3) 同时此代码在渲染中清晰雕刻 A.php页面的html(例如作为body的一个属性, es:

data-bridge="ehfwiehfe5435ubf37bf3834i"

4) 此雕刻代码是从 javascript 中检索并通过 ajax 发送的 向 B.php 发布请求

5) B.php页面获取代码并检查是否存在于C.txt文件中 6) 如果代码匹配,则从 C.txt 和页面 B.php 中弹出代码 可访问 7) 如果未发送代码(如果您尝试直接访问 B 页)或根本不匹配(如果您提供的旧代码被困 或使用自定义代码欺骗),B.php 页面死机。

这样你只能通过父页面A生成的ajax调用访问B页面。 pageB.php 的密钥仅来自 pageA.php

【讨论】:

而不是生成C.txt文件。在session_start() 上生成并在每次检查时重新生成一个$_SESSION['random_key'] 变量不是更明智吗?【参考方案6】:

将以下代码放在 ajax 调用的 php 文件的最顶部。它将执行 ajax 请求,但如果直接从浏览器调用,则会“死”。

define('AJAX_REQUEST', isset($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest');
if(!AJAX_REQUEST) die();

就我个人而言,作为额外的安全措施,我选择在“die()”之后不输出任何内容。这意味着我更喜欢只向“入侵者”显示一个空白页面,而不是给出诸如“如果”或“为什么”这样的提示,这个页面是受保护的。

【讨论】:

【参考方案7】:

此线程中建议查看标题的任何人在某种程度上都是错误的。请求中的任何内容(HTTP_REFERER、HTTP_X_REQUESTED_WITH)都可能被并非完全无能的攻击者欺骗,包括共享机密 [1]。

您无法阻止人们向您的网站发出 HTTP 请求。您要做的是确保用户在通过会话 cookie 向您网站的某些敏感部分发出请求之前必须进行身份验证。如果用户发出未经身份验证的请求,请立即停止并给他们一个 HTTP 403。

您的示例发出 GET 请求,所以我猜您关心请求的资源需求 [2]。您可以对 .htaccess 规则中的 HTTP_REFERER 或 HTTP_X_REQUESTED_WITH 标头进行一些简单的完整性检查,以阻止为明显虚假的请求(或不会听 robots.txt 的愚蠢搜索爬虫)生成新进程,但如果攻击者伪造那些,你会想要确保你的 PHP 进程尽早退出未经身份验证的请求。

[1] 这是客户端/服务器应用程序的基本问题之一。这就是它不起作用的原因:假设您有一种方法可以让您的客户端应用程序向服务器验证自身 - 无论是秘密密码还是其他方法。应用程序需要的信息必须可由应用程序访问(密码隐藏在某处或其他地方)。但是因为它在用户的计算机上运行,​​这意味着他们也可以访问这些信息:他们所需要的只是查看源代码、二进制文件或应用程序与服务器之间的网络流量,最终他们会弄清楚您的应用程序验证和复制它的机制。也许他们甚至会复制它。也许他们会编写一个聪明的 hack 来让你的应用程序完成繁重的工作(你总是可以向应用程序发送虚假的用户输入)。但无论如何,他们已经获得了所需的所有信息,没有办法阻止他们拥有这些信息,也不会阻止您的应用拥有它。

[2] 设计良好的应用程序中的 GET 请求没有副作用,因此没有人可以在服务器上进行更改。您的 POST 请求应始终使用会话加 CSRF 令牌进行身份验证,以仅让经过身份验证的用户调用它们。如果有人对此进行攻击,则意味着他们在您那里有一个帐户,而您想关闭该帐户。

【讨论】:

【参考方案8】:

这样做没有意义。它不会增加任何实际的安全性。

所有表明通过 Ajax 发出请求的标头(如 HTTP_X_REQUESTED_WITH)都可以在客户端伪造。

如果您的 Ajax 提供敏感数据或允许访问敏感操作,则需要添加适当的安全性,例如登录系统。

【讨论】:

【参考方案9】:

大多数 Ajax 请求/框架应该设置这个特定的标头,您可以使用它来过滤 Ajax v 非 ajax 请求。我用它来帮助确定大量项目中的响应类型(json/html):

if( isset( $_SERVER['HTTP_X_REQUESTED_WITH'] ) && ( $_SERVER['HTTP_X_REQUESTED_WITH'] == 'XMLHttpRequest' ) )

    // allow access....
 else 
    // ignore....
 

编辑: 您可以在您自己的 Ajax 请求中添加此内容,并在您的 javascript 代码中添加以下内容:

var xhrobj = new XMLHttpRequest();
xhrobj.setRequestHeader("X-Requested-With", "XMLHttpRequest"); 

【讨论】:

虽然不是 100% 有效(在标题被欺骗的情况下),这是一个非常快速和简单的解决方案,只允许 AJAX 调用页面。 +1 啊...这是我期望得到的解决方案类型。不幸的是,我没有使用任何框架——只是直接的 javascript/ajax。无论如何,我的代码没有设置变量,所以这对我不起作用。 -1 这并不能防止任何滥用,因为 HTTP 标头很容易被欺骗。 @9kSoft — 没有解决方案,因为问题是试图让用户的软件对用户隐藏信息。这是不可能的。 一个好的解决方案是一个服务器生成的令牌,它在 javascript 请求中发送并再次在服务器上验证。【参考方案10】:

我使用的是:PHP 会话 + 每次我发出请求时发送的哈希。这个哈希是在服务器端使用某种算法生成的

【讨论】:

【参考方案11】:

根据您的描述,我假设您正在努力防止彻底猖獗的滥用,但不需要坚如磐石的解决方案。

因此,我建议使用 cookie:

在使用 AJAX 的页面上只需 setcookie(),并检查 $_COOKIE 在 func.php 上的正确值。这将为您提供一些合理的保证,即任何调用 func.php 的人最近都访问过您的网站。

如果您想变得更高级,您可以设置和验证唯一的会话 ID(您可能已经这样做了),以确保 cookie 没有被伪造或滥用。

【讨论】:

【参考方案12】:

嗯...您可以在会话开始时生成一次性密码,您可以将其存储在 _SESSION 中,并向您的 ajax 调用添加一个参数,该参数将重新传输(类似于验证码)。它仅对该会话有效。

这可以保护您免受自动攻击,但有权访问您网站的人仍然可以手动执行此操作,但这可能是设计更复杂的东西的基础。

【讨论】:

谢谢 - 这对我的场景来说似乎有点矫枉过正。我调用的页面只是发送一封电子邮件——传递的参数是电子邮件地址。我真的只问了这个问题,因为我对 ajax 还很陌生,这似乎是未来应用程序中可能出现的问题。

以上是关于防止直接访问由ajax函数调用的文件[重复]的主要内容,如果未能解决你的问题,请参考以下文章

防止 AJAX 中的滚动重置

请大家解释一下Delphi的回调函数

如何设计API接口,请求接口时需要进行身份验证,防止第三方随意调用接口?

如何知道调用者类 C# [重复]

如何通过onRowSelect ajax事件调用jQuery? [重复]

java,防止用ajax中的url 直接访问,怎么处理呀?