将安全数据从 javascript 发送到 php

Sending secure data from javascript to php

我在 HTML/CSS/JS 中内置了一个测验系统,我最近添加了 php 以将通过 JS 获得的分数添加到我的数据库中。我正在使用 ajax 发送乐谱并在 PHP 中接收乐谱。问题是,任何人都可以通过控制台发送相同的请求,因此这种方法根本不安全。请建议我一种提高此代码安全性的方法,这样就没有人可以向我的数据库发送虚假分数请求。

JAVASCRIPT:

function addScore(gType, amount) { 
    var xhr = new XMLHttpRequest();
    xhr.open('POST', 'http://localhost/TM/backend/score.backend.php');
    xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
    xhr.onload = function() {
        console.log('score request sent: ' + xhr.responseText);
    };
    xhr.send('score=' + amount + '&gType=' + gType);
}

PHP:

    $score = $_POST["score"];
    $type = $_POST["gType"];
    echo $score;
    echo $type;

    //log in
    session_start();    
    include_once "../db/config.php";
    
    $email = mysqli_real_escape_string($conn, $_SESSION["email"]);
    if ($type == "allemand") {
        $sql = "UPDATE `users` set scoreAllemand=scoreAllemand+? WHERE email=?;";
    } else if ($type == "drapeaux") {
        $sql = "UPDATE `users` set scoreDrapeaux=scoreDrapeaux+? WHERE email=?;";
    } else if ($type == "carte") {
        $sql = "UPDATE `users` set scoreCarte=scoreCarte+? WHERE email=?;";
    } else if ($type == "italien") {
        $sql = "UPDATE `users` set scoreItalien=scoreItalien+? WHERE email=?;";
    } else if ($type == "anglais") {
        $sql = "UPDATE `users` set scoreAnglais=scoreAnglais+? WHERE email=?;";
    }
    
    // execute without parameters
    mysqli_query($conn, $sql);
    
    // security 
    $stmt = mysqli_stmt_init($conn);
    if (!mysqli_stmt_prepare($stmt, $sql)) {
        echo "SQL ERROR";
    } else {
        mysqli_stmt_bind_param($stmt, "ss", $score, $email);
        mysqli_stmt_execute($stmt);
    }

anyone is able to send the same request via console so this method isn't secure at all

...如果您使用普通回发,情况也是如此。有人可以查看请求的格式并查看正在发送的内容,然后伪造一个类似的请求(使用浏览器控制台,或单独的工具,如 PostMan 或他们自己的定制程序)。

所以 AJAX 不是这里的问题,问题是你永远不应该相信从客户端发送到服务器的任何东西,因为你永远无法 100% 确定它是如何发送的。

如果不想让任何人有可能篡改分数,就需要重新设计,让前端只提交用户的答案,然后PHP会需要检查它们并计算分数。


P.S。顺便说一句,您需要删除 mysqli_query($conn, $sql); (因为它可能会失败并且也是多余的,因为您稍后会使用参数执行查询)并且还需要删除对 mysqli_real_escape_string() 的所有调用 - 因为您'重新使用参数时,您不需要它(在某些情况下它实际上可能会主动损害数据)。

如果需要,在任何其他代码行之前写 session_start(); 也是一个好习惯,这样您就知道在需要使用任何 Session 变量之前它总是准备就绪。