问题描述
不久前我问了这个问题,我删除了这个问题,因为尽管我找到了解决问题的适当方法。
我正在建立一个可处理大量XMLHttpRequest
的网站。
我需要将登录客户端的user_id
发送到位于其他位置的php
文件,该文件会将sql
语句发送到database
,并根据登录客户端返回信息。
我没有任何 security
知识。
我对sql
和php
了解很少 。
所以我想确保我的网站安全,因此我需要一些有关安全性的建议以及将user_id
通过发送到php
文件的适当方法。
或者,即使在客户端显示user_id
也不重要。
而且,我仅将客户端的唯一user_id
存储在$_SESSION
仅此而已。
我已经完全使用此来源= 制作了我的登录/注册系统
index.php:
<?php
session_start();
?>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>TEST</title>
</head>
<body>
<?php
if (isset($_SESSION['user_id'])) {
echo ('<button>CLICK TO GET INFO IN CONSOLE</button>');
} else {
header ("Location: login.php");
exit();
}
?>
<script>
var user_id = <?php echo($_SESSION['user_id']);?>;
document.querySelector("button").onclick = function() {
var xhr = new XMLHttpRequest();
var url = "http://URL_OF_A_PHP_FILE_LOCATED_IN_A_DIFFERENT_LOCATION";
xhr.open("GET", url + "?user_id=" + user_id + "&var_1=val_1&var_2=val_2&var_3=val_3");
xhr.onload = function() {
console.log(JSON.parse(xhr.responseText));
}
xhr.send(null);
}
</script>
</body>
</html>
1楼
您不必使用javascript在PHP文件之间共享信息(即使在单独的服务器上)。
$ _SESSION被显式地用于在页面之间保留数据,因此您应该在页面内进行处理。
如果必须将user_id发送到另一台服务器上的文件,建议在PHP文件而不是Javascript(在客户端,因此很容易被滥用)中执行此操作。
您可以简单地使用来执行HTTP POST请求。
2楼
首先,我将假定您是PHP的新手,这是出于一个非常特定的原因: $_SESSION
旨在作为服务器端存储,并且在任何时候都不应转到客户端。
因为您可能在会话中存储了有意义的数据,所以您不想通过网络传输这些数据,尤其是因为您不希望任何不带偏见的人嗅探数据并最终让自己对RCE(远程代码执行)或SQL注入敞开大门攻击。
但是,当您查看单个值时,情况就不同了。 可以使用用户ID-但是,如果我对此页面进行范围为0到100的生成器攻击,并且每个数字都用作ID,该怎么办? 您需要在任何给定时间考虑这一点。 这是非常重要的。
现在-实际回答您的问题。
首先,您可以采用两种方法:确实要交出用户ID,只要您确定该ID不能用于恶意尝试,或者您可以使用具有加密值的Cookie-或将Cookie加密一般。
对于选项一,您可以这样做:
var user_id = <?=json_encode($_SESSION["user_id"])?>;
这会将您的user_id
编码为JSON(JavaScript对象表示法)-本质上本质上是有效的JavaScript。
因此,如果$_SESSION["user_id"]
恰好是一个类似于1
的整数,则结果将如下所示:
var user_id = 1;
使用加密cookie的第二种方法有点麻烦,但也更安全。 考虑一下:
<?php
$salt = openssl_random_pseudo_bytes(openssl_cipher_iv_length($cipher));
$cipher = "AES-128-CTR";
function encryptValue($value) {
$secret = "..."; // See below
$encryptedValue = openssl_encrypt($value, $cipher, $secret, 0, $salt)
. "::" . bin2hex($salt);
return $encryptedValue;
}
function decryptValue($value) {
list($encryptedValue, $salt) = explode("::", $value);
return openssl_decrypt($encryptedValue, $cipher, $secret, 0, hex2bin($salt));
}
?>
(资源: : )
现在,这是一个非常简单的基于OpenSSL扩展的加密/解密机制,它将为您加密值并将其解密。
重要的部分是$secret
。
这是用于混淆用户看到内容的加密“密码”。
因为从根本上讲,避免攻击的第一步是使无法解读发送给服务器的值的实际含义。
至少在生产环境中。
在开发中,您可能实际上将其保留为明文-但这是一个不同的主题。
因此,现在有了这两个功能,您可以执行以下操作:
<?php
$value = null;
if(array_key_exists("user_id", $_COOKIE)) {
// The user has previously been assigned a `user_id`.
$value = decrypt($_COOKIE["user_id"]);
} else {
// The user is possibly visiting for the first time, so they have no ID.
$value = get_user_id_from_somewhere();
}
?>
现在,您将获得一个包含新ID或预先发送的ID的$value
。
但是现在您需要将此值发送给客户端,以便可以在XHR请求中使用它。 好吧,您将需要先 。 完成后,您可以从第一个选项中选取示例,然后执行以下操作:
var token = <?=json_encode(encrypt($_COOKIE["user_id"]))?>;
对于“某物”,我的意思是真的-加密令牌的获取方式取决于您:)
接下来,您可能需要使用它发送XHR请求,因此您需要将其 。
您甚至可以立即使用此功能,并将token
变量与以下内容一起保存:
var url = "http://example.com/other.php?token=<?=urlencode(encrypt($_COOKIE["user_id"]))?>";
要访问该URL参数,请在other.php
使用$_GET["token"]
并使用上面的函数(或与您提出的任何其他函数)对其进行解密。
那么在这种情况下应该选择哪个选项?
-如果您非常肯定无法利用数据并将其传输给客户,因此可以将它们传输到客户端,请使用json_encode
和$_SESSION
的raw变量。
请记住,会话变量是服务器专有的。
实际上,PHP实际上会将PHPSESSION
cookie发送到客户端,该客户端使用这样的散列,看起来几乎是加密的字符串,以便在后续请求中标识访问者。
-如果您传输的数据绝对不希望客户端看到或什至不知道,请对其进行加密。
客户对您的业务逻辑(脚本的内容)了解的越少,受到攻击的机会就越小。
另外:永远不要信任用户。 这在很大程度上是不成文的,但是是黄金法则。 如果不确定,请使用您手边最安全的方法。 仅当您非常非常确定时,才将原始格式的值发送给他们-他们将能够以其所有的全部荣耀来读取它们。
json_encode
一个小注释:您还可以对整个数组进行编码: json_encode(["foo"=>"baz"])
将变为: {"foo":"baz"}
,它是有效的JSON,并且JavaScript也是如此。
因此,还有一个补充说明:如果尚未使用,请使用PHP的官方手册并开始使用 。 您可以在那里找到许多有用的工具,这些工具可以使您作为PHP开发人员的生活更加轻松。
我知道这是一个很长的答案,但是我的意思只是=)祝您应用程序好运!