我有下面的代码,它应该在单击Like按钮时将一行插入到DB表中"clicks"(由一个主AI列"id"和另一个包含用户会话id的列"user"组成)。对于每个用户,假设他们从登录中设置了会话id,我想将他们最近从表中插入的id返回给他们。因此,第一次点击按钮时,它将返回1等。我希望多个用户可以通过登录系统访问它。我想知道我的代码是否有任何重大的安全漏洞,例如结果是否可以伪造等?
index.php:
<?php
include 'init.php';
include 'connect.php';
?>
<!doctype html>
<html>
<body>
<?php
$userid = $_SESSION['user_id'];
echo '<a class="like" href="#" onclick="like_add(', $userid,
');">Like</a>';
?>
<script type ="text/javascript" src="jquery-1.11.1.min.js"></script>
<script type ="text/javascript" src="like.js"></script>
</body>
</html>
connect.php:
<?php
$servername = "localhost";
$username = "root";
$password = "";
$dbname = "DB";
$conn = new mysqli($servername, $username, $password, $dbname);
if ($conn->connect_error) {
die("Connection failed: " . $conn->connect_error);
}
?>
init.php:
<?php
session_start();
$_SESSION['user_id']='1';
$userid = $_SESSION['user_id'];
include 'connect.php';
include 'like.php';
?>
like.js:
function like_add(userid) {
$.post('like_add.php', {userid:userid}, function(data) {
if (data == 'success'){
add_like($userid);
} else{
alert(data);
}
});
}
like.php:
<?php
function add_like($userid){
include 'connect.php';
$stmt = $conn->prepare("INSERT INTO clicks (user) VALUES (?)");
$stmt->bind_param("s", $userid);
$stmt->execute();
$stmt = $conn->prepare("SELECT max(id) FROM clicks WHERE user=?");
$stmt->bind_param("s", $userid);
$stmt->execute();
$stmt->bind_result($click);
$stmt->fetch();
echo $click;
$stmt->close();
}
?>
like_add.php:
<?php
include 'init.php';
if (isset($userid)) {
$userid = $userid;
add_like($userid);
}
?>
如果同一用户几乎同时发送多个请求,则您的查询可能会给出不正确的结果,以防您的查询不会返回当前插入的id。您可以使用last_insert_id()mysql函数,该函数会为您提供上一次插入的自动增量值,而不管其他请求是否同时更新了表
此外,您不需要在ajax请求中传递user_id参数,因为您无论如何都可以从会话中获得它。传递user_id可以被认为是一个安全漏洞,因为任何人都可以修改onclick处理程序并触发其他用户的点击。我建议尽可能避免以纯文本形式发送用户ID作为响应。
添加更多安全性:在连接脚本中。将$servername、$username等更改为常量。这些不需要改变,你也不希望它们被改变。
你的会话有任何类型的检查吗?会话比cookie更安全,但当用户登录时,它们可能会在传输过程中被劫持。要为会话添加一些安全性,请在用户登录时使用session_regenerate_id()函数,这将生成一个新的会话id,因此,如果用户id被劫持,它将毫无用处,因为它将发生更改。还可以对会话进行其他检查以确保它们的安全,但这是一个很好的快速添加额外级别的方法。
@nomistic提出了一些很好的建议,尤其是在密码和其他敏感信息的加密方面。使用crypt()函数或PHP的密码哈希API-http://php.net/manual/en/book.password.php.也是个好办法。
这在php方面看起来相当不错。您正在使用会话ID进行用户验证,并且已准备好SQL插入。(有一个问题,你为什么要设置$_SESSION['user_id']='1'
?你计划只拥有一个用户吗?这对我来说似乎没有必要)
但是,您可能需要加强数据库端的安全性。为公共数据库访问设置一个不同的用户并限制数据库端的操作可能是个好主意。例如,如果他们要做的只是select
或插入,那么该用户应该只有这样做的权限。我不会使用你的root
帐户。尽管这可能不是一个巨大的风险(至少在前两次,您在SQL注入方面做得很好),但添加另一层总是一个好主意。
在处理安全性时,考虑一个"用例"场景是很有帮助的。您正在存储什么类型的数据?这是某人真正想要的东西吗?(例如,它是财务方面的吗?)考虑人的因素总是一个好主意。有人想花一天以上的时间试图破解你的数据吗(这对他们来说值得吗?)。
此外,虽然这在这里并不明显,但您可能需要确保您有一个良好的加密密码形式。
另一个想法是:即使风险很小,每天运行备份也不是一个坏主意,这样您就可以在最坏的情况下恢复数据。
编辑:
既然有人问它,下面是如何在数据库端设置安全性:
首先创建一个新用户(遵循此模式):
CREATE USER 'newuser'@'localhost' IDENTIFIED BY 'password';
授予权限的工作方式如下:
GRANT [type of permission] ON [database name].[table name] TO ‘[username]’@'localhost’;
特权类型包括ALL PRIVILEGES
、CREATE
、DROP
、DELETE
、INSERT
、SELECT
、UPDATE
、GRANT OPTION
。
如果您想了解更多信息,请参阅以下文档:https://dev.mysql.com/doc/refman/5.1/en/adding-users.html