我已经为我的网站创建了一个Ajax登录名,但我觉得我可以优化它,但我不确定如何以及在哪里。
问题:
- 如何优化我的代码?
- 代码安全吗?有什么方法可以打破它(注射等)吗?
此外,当我尝试登录时,目前大约需要 1 秒来处理登录(在本地主机上)。这么长吗?
这是我的Ajax电话:
$(document).ready(function() {
$(document).on("submit", "form", function(event) {
event.preventDefault();
$.ajax({
url: 'assets/php/login_script.php',
type: 'POST',
data: $(this).serialize(),
success: function(data) {
if (data == true) {
window.location.href = "index.php";
} else {
$("input[name=password_field]").focus();
$(".error").html(data);
}
}
});
});
});
下面是 PHP 脚本:
<?php
include_once("access.php");
$cxn = mysqli_connect($host, $user, $pass, $db) or die ("Couldn't connect to the server. Please try again.");
$username = $_POST["username"];
$password = $_POST["password"];
$date = date('Y-m-d h:i:s', time());
$ip_address = get_ip_address();
$expire = time() + 86400 * 365;
$options = array('cost' => 12);
$hash_password = password_hash($password, PASSWORD_BCRYPT, $options);
/* Log the login request. */
$stmt = $cxn->prepare("INSERT INTO login_logs (log_id, username, password, datetime, ip_address) VALUES ('', ?, ?, ?, ?)");
$stmt->bind_param('ssss', $username, $hash_password, $date, $ip_address);
$stmt->execute();
/* Get user information from database. */
$stmt = $cxn->prepare('SELECT * FROM users WHERE username = ?');
$stmt->bind_param('s', $username);
$stmt->execute();
$result = $stmt->get_result();
/* If a result exists, continue. */
if ($result->num_rows > 0) {
while ($row = $result->fetch_assoc()) {
$db_username = $row['username'];
$db_password = $row['password'];
$random_hash = password_hash(time() . $db_username . time(), PASSWORD_BCRYPT, $options);
/* Password matches. */
if (password_verify($password, $db_password)) {
/* Get user's cookie information in database. */
$stmt2 = $cxn->prepare("SELECT * FROM cookies WHERE username = ?");
$stmt2->bind_param('s', $db_username);
$stmt2->execute();
$result2 = $stmt2->get_result();
/* If a result exists, update the cookie. */
if ($result2->num_rows > 0) {
$stmt = $cxn->prepare("UPDATE cookies SET hash = ? WHERE username = ?");
$stmt->bind_param('ss', $random_hash, $db_username);
$stmt->execute();
setcookie("user", $db_username, $expire, "/");
setcookie("hash", $random_hash, $expire, "/");
} else {
$stmt = $cxn->prepare("INSERT INTO cookies (cookie_id, username, hash) VALUES ('', ?, ?)");
$stmt->bind_param('ss', $db_username, $random_hash);
$stmt->execute();
setcookie("user", $db_username, $expire, "/");
setcookie("hash", $random_hash, $expire, "/");
}
echo true;
} else {
echo "Incorrect credentials.";
}
}
} else {
echo "Incorrect credentials.";
}
function get_ip_address() {
$ip_address = '';
if (getenv('HTTP_CLIENT_IP'))
$ip_address = getenv('HTTP_CLIENT_IP');
else if(getenv('HTTP_X_FORWARDED_FOR'))
$ip_address = getenv('HTTP_X_FORWARDED_FOR');
else if(getenv('HTTP_X_FORWARDED'))
$ip_address = getenv('HTTP_X_FORWARDED');
else if(getenv('HTTP_FORWARDED_FOR'))
$ip_address = getenv('HTTP_FORWARDED_FOR');
else if(getenv('HTTP_FORWARDED'))
$ip_address = getenv('HTTP_FORWARDED');
else if(getenv('REMOTE_ADDR'))
$ip_address = getenv('REMOTE_ADDR');
else
$ip_address = 'UNKNOWN';
return $ip_address;
}
?>
如何优化脚本以使其看起来更好、更快等?
一秒延迟的问题是连接到localhost
,这是 PDO 的问题。只需将localhost
更改为127.0.0.1
即可解决延迟问题。
其余代码对我来说看起来不错很干净,干得好。 :)
看起来总体不错。乍一看有几件事:
大于 0 在 if 语句中是多余的:
if ($result->num_rows) {
if ($result2->num_rows) {
有人会认为您的用户名是唯一的。因此,您不需要循环结果。
假设_id字段是自动增量主键字段,则无需在查询中指定它们。 即从字段和值列表中删除它们。
检查您对 IP 地址的使用情况。您在此处使用它来确保登录安全性,但您是从一系列用户提供的标头中获取的。我建议,除非有充分的理由获得"真正的"IP,否则你应该使用REMOTE_ADDR。
您的"选择饼干,我选择了什么吗?更新或插入"逻辑可以通过使用插入...在重复密钥更新...有关语法,请参阅有关插入的MySQL手册。
您正在使用 Cookie 来存储用户名/哈希。考虑您是否真的需要这样做,因为它增加了您的逻辑的复杂性,即每次需要时都必须检查cookie中的用户名是否应该是。如果你能侥幸使用_SESSION美元,我建议这样做。