当前位置: 首页 > 面试题库 >

如何使用PHP和jQuery发送安全的AJAX请求

卜瀚漠
2023-03-14
问题内容

问题

因此,一段时间以来,我一直在尝试使用不同的AJAX方法将数据发送到将要处理并存储在MySQL数据库中的服务器。

AJAX请求命中的页面api.php使用PHP的PDO准备好的语句来保存数据,因此MySQL注入并不是真正的问题,还需要处理密码或需要加密的数据,api.php这不是我要的这里。我的问题更多地涉及从客户端传输到服务器时如何确保数据的安全性。

方法

我目前有(对于下面包含的登录示例):

  • 域上运行的SSL证书/ HTTPS。
  • 某些AJAX请求(显然没有此登录请求示例,因为没有会话开始)仅在PHP会话在整个站点上均有效(在本例中login.phpapi.php本例中均使用)时才有效。
  • api.php访问功能时的速率限制。
  • PHP PDO在与数据库内部交互时准备了语句api.php
  • 加密内部的敏感数据api.php(与问题无关)。

问题

最后,我的问题是:

  1. 这种使用异步HTTP(Ajax)请求的方法是否足以安全使用,而不是仅仅将数据提交到PHP页面并进行重定向?(这样可以改善用户体验)。
  2. 如何检查用户的发送数据没有被篡改?
  3. 我是否做了足够的努力来保护用户的数据,如果没有,我还能做什么?

这个例子

我了解每个人都有不同的方法来处理其站点的数据并传输该数据。我也了解,无论您做什么,都永远不会100%受保护,因为系统中可能存在无法解决的漏洞和方法。我正在寻找有关安全发送数据的一般方法的反馈/改进,而不是批评下面的特定代码,因为这仅是示例。但是,欢迎提出任何建设性的答案。感谢您抽出宝贵的时间阅读/回答。

function loginUser() {
    var process = "loginUser";
    var data = $("form").serializeArray();
    data[1].value = SHA512(data[1].value); // sha then encrypt on api.php page 
    data = JSON.stringify(data);

    $("#loginButton").html('<i class="fa fa-spinner fa-pulse fa-lg fa-fw"></i> Login');
    $.ajax({
        type: "POST",
        url: "api.php",
        data: {"process": process, "data": data},
        success: function(data) {
            if (data.response.state == "success") {
                // if api.php returns success, redirect to homepage
            } else {
                // if api.php returns failure, display error
            }  
        },
        error: function(jqXHR, textStatus, errorThrown, data) {
            // error handling
        },
        dataType: "json"
    });
}

问题答案:

1.检查ORIGIN标头

根据OWASP的指定,这还不够,但建议:

尽管从您自己的浏览器中欺骗任何标头很简单,但除非通过XSS漏洞,否则在CSRF攻击中通常是不可能的。这就是为什么检查标头是CSRF防御中合理的第一步,但是由于它们并不总是存在,因此通常不能单独考虑将其视为足够的防御。

而由Mozilla:

Origin标头被认为有助于防止JSON数据盗用和CSRF攻击。Origin提供的信息(一些上下文请求创建信息)应向Web服务器提供有关请求可信度的提示[…]

检查HTTP_ORIGIN标题可以写成:

    header('Content-Type: application/json');

    if (isset($_SERVER['HTTP_ORIGIN'])) {
        $address = 'http://' . $_SERVER['SERVER_NAME'];
        if (strpos($address, $_SERVER['HTTP_ORIGIN']) !== 0) {
            exit(json_encode([
                'error' => 'Invalid Origin header: ' . $_SERVER['HTTP_ORIGIN']
            ]));
        }
    } else {
        exit(json_encode(['error' => 'No Origin header']));
    }

1.(之二)检查REFERER标头

再次从OWASP:

如果没有Origin头
,请确认Referer头中的主机名与站点的来源匹配。检查引荐是防止嵌入式网络设备上CSRF的一种常用方法,因为它不需要每个用户状态。.这种CSRF缓解方法也常用于未经身份验证的请求[…]

使用来检查,HTTP_REFERER在PHP中也非常简单$_SERVER['HTTP_REFERER'],您可以使用来更新上面的代码。

请务必 始终进行真正的检查:不要只检查 example.com 或 _api.example.com, 而不要检查完整的
https://example.com 。为什么呢 因为您可以使用诸如
_api.example.com.hacker.com之

类的来源来欺骗此检查。

2.生成CSRF令牌

简而言之,已经给出了一个专门针对PHP的解释清楚的答案:

  1. 生成令牌:
        session_start();
    if (empty($_SESSION['csrf_token'])) {
        $_SESSION['csrf_token'] = bin2hex(random_bytes(32));
    }
  1. 通过meta(例如Github)将其添加到生成的视图中:

    <meta name="csrf-token" content="<?= $_SESSION['csrf_token'] ?>">
    
  2. 设置jQuery ajax调用以包含此令牌:

        $.ajaxSetup({
        headers : {
            'CsrfToken': $('meta[name="csrf-token"]').attr('content')
        }
    });
  1. 服务器端检查您的AJAX请求:
        session_start();
    if (empty($_SESSION['csrf_token'])) {
        $_SESSION['csrf_token'] = bin2hex(random_bytes(32));
    }

    header('Content-Type: application/json');

    $headers = apache_request_headers();
    if (isset($headers['CsrfToken'])) {
        if ($headers['CsrfToken'] !== $_SESSION['csrf_token']) {
            exit(json_encode(['error' => 'Wrong CSRF token.']));
        }
    } else {
        exit(json_encode(['error' => 'No CSRF token.']));
    }

大多数PHP框架都有自己的CSRF实现,或多或少都基于相同的原理。

4.保护您的服务器

  • 限制您的请求数。
  • 尽可能使用https。
  • 阻止错误的查询。
  • 保护POST请求。

5.永远不要相信用户输入

正如@
blue112所说,这是最基本的安全原则之一。

在此处输入图片说明



 类似资料:
  • 问题内容: 只是知道,是否可以通过Ajax请求安全地发送密码? 我有一个登录框,它调用ajax请求来尝试登录/传递并检索带有错误(如果有)的JSON对象。 我应该改用表单重定向吗? [编辑] 将加密的密码存储在数据库中不是解决方案,因为ajax发送的登录名和密码是访问数据库本身(内部应用程序)的登录名/密码。 问题答案: 发送第三方无法拦截的内容的唯一方法是使用HTTPS而不是常规HTTP。这样,

  • 问题内容: 我需要向运行守护程序的端口8080发送AJAX请求。 问题答案: 您不能跨域,子域或端口号信息。但是,如果您可以同时访问守护程序 和 请求站点,则可以使用JSONP 。如果需要返回数据,则需要支持查询参数并以正确的格式返回它。 将信息传递给守护程序: 现在,只需确保您的守护程序可以处理该参数。例如,如果守护程序的返回(唯一写入页面的内容)应如下所示: 对于键/值对: 对于数组: 如果没

  • 问题内容: 我想使用jQuery将JavaScript数组发送到servlet 。 当我使用 它返回空值。 如何访问这些值? 问题答案: 将数组作为JS对象的值发送,因此最终得到。 在servlet中,您需要在请求参数名称后加上。 jQuery附加了它们以便对弱类型语言(如PHP)友好。

  • 问题内容: 如何使用jQuery明确提出AJAX HTTPS GET请求?我正在尝试执行以下操作。在https页面上,我有一行代码,但是出现以下错误 如果相对资源来自https页面,为什么AJAX调用会尝试使用HTTP协议访问页面?如果$ .get(url)方法默认执行此操作,那么我如何使用jQuery进行显式的HTTPS GET请求?在http://forum.jquery.com/topic/

  • 所以我有这个问题,我不可能读取/保存文件由Ajax/jQuery我发送使用这个 这是我对发送JQuery的尝试: 而且,我无论如何也不能用PHP读取它,$_files是空的,$_post也是...

  • 问题内容: 帮助,如果您可以- 情况: http://foobar.com包含一个远程托管的Javacript文件(http://boobar.com/stuff.js)。 目标是从foobar.com上的远程托管php脚本中获取警报 我在stuff.js中尝试了以下代码: 没运气。 也没有运气。 在php端,我尝试了以下两种方法: 在Firefox中,出现安全错误。我了解它认为我违反了安全模型。