简体   繁体   English

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

[英]Secure ajax GET/POST request for server

suppose I work with some kind of API and my file server.php handles the connection to the API service.假设我使用某种 API,并且我的文件server.php处理与 API 服务的连接。 on my client side I use AJAX call like this:在我的客户端,我使用这样的 AJAX 调用:

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

in my server.php I handle it like this:在我的 server.php 中,我像这样处理它:

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

function get_content(){...}

i just wonder what prevents any one send AJAX call with the same getContent parameter and get all my data?我只是想知道是什么阻止了任何人使用相同的 getContent 参数发送 AJAX 调用并获取我的所有数据? how can i secure it and make sure only calls from my application will get the relevant data back?我如何保护它并确保只有来自我的应用程序的调用才能取回相关数据?

thank you!谢谢你!

I guess you are concerned about CSRF attacks.我猜你担心 CSRF 攻击。 Read more about this here: https://www.owasp.org/index.php/Cross-Site_Request_Forgery_%28CSRF%29_Prevention_Cheat_Sheet在此处阅读更多相关信息: https ://www.owasp.org/index.php/Cross-Site_Request_Forgery_%28CSRF%29_Prevention_Cheat_Sheet

One of the mostly used option to secure your request will be: - Generate a token and send it with the request for a session.保护您的请求的最常用选项之一是: - 生成令牌并将其与会话请求一起发送。 This token can be identified by your WebServer as originating from a specific client for a specific session此令牌可以由您的 WebServer 识别为来自特定客户端的特定会话

i just wonder what prevents any one send AJAX call with the same getContent parameter and get all my data?我只是想知道是什么阻止了任何人使用相同的 getContent 参数发送 AJAX 调用并获取我的所有数据?

Nothing.没有什么。 This URL is public thus anyone can make requests to it.此 URL 是公开的,因此任何人都可以向它提出请求。

how can i secure it and make sure only calls from my application will get the relevant data back?我如何保护它并确保只有来自我的应用程序的调用才能取回相关数据?

You can pass additional data (for example, some hashed value) that is verified on the server side.您可以传递在服务器端验证的其他数据(例如,一些散列值)。

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

and

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

function get_content(){...}

i just wonder what prevents any one send AJAX call with the same getContent parameter and get all my data?我只是想知道是什么阻止了任何人使用相同的 getContent 参数发送 AJAX 调用并获取我的所有数据?

The same way you would protect the data in any other request (eg with user authentication).与保护任何其他请求中的数据的方式相同(例如,使用用户身份验证)。 There's nothing special about Ajax in regards to HTTP as far as the server is concerned.就服务器而言,关于 HTTP 的 Ajax 没有什么特别之处。

how can i secure it and make sure only calls from my application will get the relevant data back?我如何保护它并确保只有来自我的应用程序的调用才能取回相关数据?

You can't.你不能。 The user can always inspect what their browser is asking the server for and replicate it.用户总是可以检查他们的浏览器向服务器请求什么并复制它。

Generally, people authenticate users rather than applications.通常,人们对用户而不是应用程序进行身份验证。

2022 Update 2022 更新

This is a 7 year old post and the link in the link-only "accepted" answer is broken.这是一篇已有 7 年历史的帖子,仅链接“已接受”答案中的链接已损坏。

So, I'm going to offer a basic walkthrough and a complete model.所以,我将提供一个基本的演练和一个完整的模型。

Remember, the $_SESSION will be preserved even in the AJAX handler, if it's all from the same domain.请记住,如果$_SESSION都来自同一个域,即使在 AJAX 处理程序中也将保留它。 So, you can use that to check things.所以,你可以用它来检查事情。

Use $_POST使用$_POST

I presume you're using $_POST and not $_GET since you're concerned about security.我假设您使用的是$_POST而不是$_GET因为您担心安全性。 If not, then much of this might not be important anyway.如果不是,那么其中大部分内容可能并不重要。

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

Ensure the $_SERVER['HTTP_REFERER'] is from your own site确保$_SERVER['HTTP_REFERER']来自您自己的站点

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

If you're not sure what this should be, run a test on your own server to see what this should be:如果您不确定这应该是什么,请在您自己的服务器上运行测试以查看应该是什么:

echo $_SERVER['HTTP_REFERER'];

Verify XMLHTTP/AJAX request via $_SERVER array通过$_SERVER数组验证 XMLHTTP/AJAX 请求

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

Use a token使用令牌

This is the hard part, but not too hard.这是困难的部分,但不是太难。

  1. Create the token创建令牌
  2. Set the token in $_SESSION$_SESSION中设置令牌
  3. Put the token in the AJAX header将令牌放在 AJAX 标头中
  4. AJAX responder: confirm the AJAX header token with the $_SESSION token AJAX 响应者:使用$_SESSION令牌确认 AJAX 标头令牌

send_from_me.php 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();

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

ajax_responder.php 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

Let's put all of this into a working example让我们将所有这些放入一个工作示例中

sending_from.php send_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.';
        } );

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

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

        // 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 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 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'];

?>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM