服务器的安全ajax GET/POST请求

问题描述 投票:0回答:4

假设我使用某种 API,并且我的文件 server.php 处理与 API 服务的连接。在我的客户端,我使用 AJAX 调用,如下所示:

$http({
         url : 'server/server.php',
         method : 'GET',
         data : { getContent : true }
     });

在我的 server.php 中我这样处理:

if(isset($_GET['getContent'])){
    $content = get_content();
}

function get_content(){...}

我只是想知道是什么阻止任何人使用相同的 getContent 参数发送 AJAX 调用并获取我的所有数据?我如何保护它并确保只有来自我的应用程序的调用才能取回相关数据?

谢谢你!

javascript php jquery ajax get
4个回答
6
投票

我猜您担心 CSRF 攻击。在这里阅读更多相关信息:https://www.owasp.org/index.php/Cross-Site_Request_Forgery_%28CSRF%29_Prevention_Cheat_Sheet

确保您的请求最常用的选项之一是: - 生成令牌并将其与会话请求一起发送。您的 Web 服务器可以将该令牌识别为源自特定会话的特定客户端


4
投票

2022 更新

这是一篇 7 年前的帖子,仅链接“已接受”答案中的链接已损坏。

因此,我将提供基本演练和完整模型。

请记住,如果

$_SESSION
全部来自同一域,即使在 AJAX 处理程序中,它也会被保留。所以,你可以用它来检查事情。

使用
$_POST

我认为您正在使用

$_POST
而不是
$_GET
,因为您担心安全问题。如果不是,那么其中大部分内容可能并不重要。

if ($_SERVER['REQUEST_METHOD'] === 'POST') {
  $post_method = true;
}

确保
$_SERVER['HTTP_REFERER']
来自您自己的网站

if ( (!empty($_SERVER['HTTP_REFERER']))
&&   ($_SERVER['HTTP_REFERER'] === "https://example.tld/my_sending_page.php") ) {
  $from_my_server = true;
} 

如果您不确定这应该是什么,请在您自己的服务器上运行测试以查看这应该是什么:

echo $_SERVER['HTTP_REFERER'];

通过
$_SERVER
数组验证XMLHTTP/AJAX请求

if ( (!empty($_SERVER['HTTP_X_REQUESTED_WITH']))
&&   ( strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) === 'xmlhttprequest') ) { 
  $ajax = true; 
} else { 
  $ajax = false; 
} 

使用代币

这是最难的部分,但不是太难。

  1. 创建代币
  2. $_SESSION
  3. 中设置令牌
  4. 将令牌放入 AJAX 标头中
  5. AJAX 响应器:使用
    $_SESSION
    令牌
  6. 确认 AJAX 标头令牌

send_from_me.php

// Create the token
//$token = md5(rand(10000,99999));  // Not recommended, but possible
$token = bin2hex(random_bytes(64));

// Store in SESSION
$_SESSION["token"] = $token;
// Assuming your AJAX is this
const AJAX = new XMLHttpRequest();

...
AJAX.open(...);

// This goes inside your AJAX function somewhere after AJAX.open and before AJAX.send
//
AJAX.setRequestHeader("ajax-token", "<?php echo $_SESSION["token"]; ?>");
//
// That creates $_SERVER['HTTP_AJAX_TOKEN'] which we can use later

...
AJAX.send(...);

ajax_responder.php

session_start(); // Must have

if ($_SERVER['HTTP_AJAX_TOKEN'] === $_SESSION["token"]) {
  $token_match = true;
} else {
  echo "No script kiddies!";
  exit();
}

// Now it's safe for your AJAX responder to proceed

让我们将所有这些放入一个工作示例中

sending_from.php

<?php

session_start();

$token = bin2hex(random_bytes(64));
$_SESSION["token"] = $token;

?>

<!DOCTYPE html>
<html>
  <head>
    <title>My AJAX Sender</title>
  </head>
  <body>

    <script>
      function ajaxFormData(formID, postTo, ajaxUpdate) {

        // Bind a new event listener every time the <form> is changed:
        const FORM = document.getElementById(formID); // <form> by ID
        const FD = new FormData(FORM); // Bind to-send data to form element
        const AJAX = new XMLHttpRequest(); // AJAX handler

        // This runs when AJAX responds
        AJAX.addEventListener( "load", function(event) {
          document.getElementById(ajaxUpdate).innerHTML = event.target.responseText;
        } );

        // This runs if AJAX fails
        AJAX.addEventListener( "error", function(event) {
          document.getElementById(ajaxUpdate).innerHTML =  'Oops! Something went wrong.';
        } );

        // Open the POST connection
        AJAX.open("POST", postTo);

        // Add your token header
        AJAX.setRequestHeader("ajax-token", "<?php echo $_SESSION["token"]; ?>");

        // Data sent is from the form
        AJAX.send(FD);

      }
    </script>

    <div id="ajax_changes">Replace me with AJAX</div>

      <form id="ajaxForm">
        <input type="text" name="the_simple_response">
        <button type="button" onclick="ajaxFormData('ajaxForm', 'ajax_responder.php', 'ajax_changes');">Send my Secure AJAX</button>
      </form>

  </body>
</html>

ajaxcheck.inc.php

<?php

$mysite = 'https://example.tld';

// All in one test
if (($_SERVER['REQUEST_METHOD'] == 'POST')
&& ((!empty($_SERVER['HTTP_REFERER'])) && ($_SERVER['HTTP_REFERER'] === "$mysite/my_sending_page.php"))
&& ((!empty($_SERVER['HTTP_X_REQUESTED_WITH'])) && ( strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) === 'xmlhttprequest'))
&& ($_SERVER['HTTP_AJAX_TOKEN'] === $_SESSION["token"])) {
  
  $ajax_legit = true;
  
} else {
  
  echo "No script kiddies!";
  exit();
  
}

?>

ajax_responder.php

<?php

session_start();

// Do all that checking we're learning about by neatly including the file above
require_once('ajaxcheck.inc.php');

// Process your AJAX
echo $_POST['the_simple_response'];

?>

3
投票

我只是想知道是什么阻止任何人使用相同的 getContent 参数发送 AJAX 调用并获取我的所有数据?

什么也没有。该 URL 是公开的,因此任何人都可以向它发出请求。

我如何保护它并确保只有来自我的应用程序的调用才能取回相关数据?

您可以传递在服务器端验证的附加数据(例如,一些哈希值)。

$http({
     url : 'server/server.php',
     method : 'GET',
     data : { getContent : true, hash : '0800fc577294c34e0b28ad2839435945' }
 });

if(isset($_GET['getContent']))
{
    if(isset($_GET['hash']) && validateHash($_GET['hash']))
    {
        $content = get_content();
    }
}

function get_content(){...}

2
投票

我只是想知道是什么阻止任何人使用相同的 getContent 参数发送 AJAX 调用并获取我的所有数据?

与保护任何其他请求中的数据相同的方式(例如,通过用户身份验证)。就服务器而言,Ajax 与 HTTP 没有什么特别之处。

我如何保护它并确保只有来自我的应用程序的调用才能取回相关数据?

你不能。用户始终可以检查浏览器向服务器请求的内容并复制它。

通常,人们对用户而不是应用程序进行身份验证。

© www.soinside.com 2019 - 2024. All rights reserved.