保证正确Ajax调用参数值的最佳方式 [英] Best way to guarantee correct Ajax calls parameter values

查看:124
本文介绍了保证正确Ajax调用参数值的最佳方式的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在一个需要一些ajax调用的网站上工作,以提高灵活性和性能。
我的ajax电话是一个排名系统。我需要使用ajax(storeID,clientID,orderID)处理三个输入值。要使用ajax提交操作,我想确保发送的参数值未被使用Web工具的用户修改。所以我正在考虑三种不同的方式来保证发送的信息没有改变:

I am working on a website that requires some ajax calls in order to improve flexibility and performance. My ajax calls is for a ranking system. I need three input values to be processed with ajax (storeID, clientID, orderID). To submit an action with ajax, I want to make sure that the parameters values sent were not modified by users using web tools. So I was thinking of three different ways to guarantee that the information sent were not changed:


  1. 发送一个额外的值加密所有数据一起发送。所以在服务器端处理ajax时,我可以重新加密发送的数据,看看加密结果是否匹配发送的加密值。

  1. Send an extra value that is the encryption of all the data sent all together. So at the server side while processing ajax, I can re encrypt the data sent and see if the encryption result matches the encryption value sent.

发送所有数据作为一个加密值。然后在执行ajax时在服务器上,我可以解密数据并重新分配值。

Send all the data as one encrypted value. Then on the server while doing the ajax, I can decrypt the data and assign the values again.

只发送orderID及其加密,然后使用方法(1 )验证orderID是否不更改,并使用数据库查询,获取其他两个信息。

Send only the orderID and its encryption then using method (1) verify that the orderID is not changed, and using the database query, fetch the two other information.

这是我对以下三种方式的看法:

Here's my opinion on each of the three ways:


  1. 消耗内存,因为我必须发送orderID,clientID,storeID,encryptedID。此外,在ajax调用中监视的信息将会向用户提供有关他们对订单进行评级的信息。

  1. Consumes memory since I have to send orderID, clientID, storeID, encryptedID. Moreover, the information monitored in the ajax call will give people information about what happens when they rate an order.

我在线检查了mcrypt_encrypt和mcrypt_decrypt,我们从未用过他们我看到他们产生一个长字符串,但我更喜欢保持我的数据发送短或看起来像md5加密数据。有更好的方法吗?

I checked online for mcrypt_encrypt and mcrypt_decrypt but I've never used them. I saw that they produce a long string, but I prefer to keep my data sent short or look like the md5 encrypted data. Is there better methods ?

这是一个优雅的方式,它看起来很直接,但它需要一些MySQL干预,这可能是耗时的,特别是当数据增长未来。

This is the elegant way, it looks straight forward but it needs some MySQL intervention, which could be time consuming especially when data grows in the future.

那么你认为哪一个更好?如果您有更多的方式欣赏,如果您在这里分享。谢谢

So which one do you think is better ? If you have more ways I appreciate if you share them here. Thank you

我想避免的场景示例:
点击一个按钮将通过传递产品ID来提交一个使用AJAX的表单。用户转到源代码,将产品的ID从X更改为Y.现在用户单击按钮并提交表单,并且ID Y的产品受到影响。您可以看到,发送的参数值不受保护,可以修改。我正在寻找一种方式来保证发送的参数值是正确的,而不会被修改。

Example of scenario I want to avoid: Clicking a button will submit a form using AJAX by passing the Product ID. A user go to the source code, and change the ID of the product from X to Y. Now the user clicks the button and the form was submitted and the product of ID Y was be affected. As you can see, the parameter values sent are not secured and can be modified. I am searching for a way to guarantee that the parameter values sent are correct and not modified.

PS :这个问题不在于CSRF处理

PS: This question is not about CSRF handling.

推荐答案

一个相当简单的方法将是 salt 对于保存在服务器上的秘密密钥(以及以任何方式暴露给用户的永不),只有(即sha / md5等)哈希的三个参数散列。

A fairly simple way would be to salt a basic forward-only (i.e sha/md5 etc.) hash of the three parameters against a secret key kept on the server (and never exposed to users in any way).

然后,当您收到用户的请求时,您可以简单地复制此只向前的散列过程,以确保数据未被篡改,类似于大多数站点实施身份验证,而不必存储

Then, when you receive the request from the user you can simply replicate this forward-only hashing process to ensure that the data hasn't been tampered with, similar to how most sites implement authentication without having to store a plaintext copy of the user's password in their database.

例如:

define('SUPER_SECRET_KEY', 'foobar123'); // our 007 secret key to hash requests against

function generateToken($storeID, $clientID, $orderID) {
    return hash('sha256', SUPER_SECRET_KEY . "/{$storeID}/{$clientID}/{$orderID}");
}

function validateToken($token, $storeID, $clientID, $orderID) {
    return generateToken($storeID, $clientID, $orderID) === $token;
}

正如我所说,现在这是一个非常基本的起点。使用静态 salt 值不会非常有效,您仍然可以自己重新开始攻击(即有人在同一个令牌/ clientID / storeID / orderID组合中发送垃圾邮件)一次又一次)。

Now this is, as I said, a very basic starting point. Using a static salt value isn't going to be very effective, and you still leave yourself open to replay attacks (i.e someone spamming that same token/clientID/storeID/orderID combination over and over again).

打击重播攻击的一种方法是生成一个 salt 的请求,rel =nofollow> nonce

One way to combat replay attacks is to generate a nonce for each request to act as the salt.

另一个超级使用 nonces 的重要伪代码的基本示例:

Another super basic example using nonces, heavy pseudocode ahead:

function generateNonce() {
    return hash('sha512', mt_rand() . time()); // please make a more secure nonce generator than this :)
}

// We need a way to retrieve the nonce for a particular request:
function generateLookup($storeID, $clientID, $orderID) {
    return hash('sha256', "{$storeID}/{$clientID}/{$orderID}");
}

function generateToken($nonce, $storeID, $clientID, $orderID) {
    $lookup = generateLookup($storeID, $clientID, $orderID);

    // Store the $nonce and $lookup somewhere (i.e a database)
    $db->query("INSERT INTO ... (nonce,lookup,expired) VALUES ('$nonce','$lookup','N')");

    return hash('sha256', "{$nonce}/$storeID/$clientID/$orderID");
}

function validateToken($token, $storeID, $clientID, $orderID) {
    $lookup = generateLookup($storeID, $clientID, $orderID);
    $rows = $db->query("SELECT nonce FROM ... WHERE lookup = '$lookup' AND expired = 'N'"); // again, pseudocode for retrieving the nonce from the persistent store
    if (count($rows) !== 0) {
        $nonce = $rows[0]['nonce'];
        // expire the nonce (note: these database queries should be in a transaction)
        $db->query("UPDATE ... SET expired = 'Y' WHERE $lookup = '$lookup' AND nonce = '$nonce'");
        return generateToken($nonce, $storeID, $clientID, $orderID) === $token;
    }
    return false;
}

然后,您的基本工作流程将成为:

Then your basic workflow would become:

在GET

$data = // retrieve data
$token = generateToken(generateNonce(), $data['storeID'], $data['clientID'], $data['orderID']);

// output the $token value in a hidden field in your form

在POST

if (validateToken($_POST['token'], $_POST['storeID'], $_POST['clientID'], $_POST['orderID'])) {
    // All good
}
else {
    echo "Back, ye filthy hacker!";
}

这篇关于保证正确Ajax调用参数值的最佳方式的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆