如果提供了合格令牌,则更新数据库表行



我的代码工作得很好,但这是有效的代码,像第16行(注释)吗?我正在考虑使用$row并与上面提到的变量进行比较,而不是编写另一个SQL查询。

我尝试使用变量和$row['field name'],但它抛出了一个错误:

尝试访问null类型值上的数组偏移

代码
<?php
require('../private/autoload.php');
if(isset($_GET['token'])){
$msg = "Email verified successfully, thank you.";
$token = $_GET['token'];
$email_status = "active";
$sql = "SELECT `email_token`, `email_status` FROM `users` where `email_token` = ? AND `email_status` = 'inactive' LIMIT 1";
$stmt = $conn->prepare($sql);
$stmt->bind_param("s", $token);
$stmt->execute();
$result = $stmt->get_result();
$exist = $result->num_rows;
if($exist == 0 ){
// $row = $result->fetch_array(MYSQLI_ASSOC);
$sql = "SELECT `email_token`, `email_status` FROM `users` where `email_token` = ? AND `email_status` = ? LIMIT 1";   // Line 16
$stmt = $conn->prepare($sql);
$stmt->bind_param("ss", $token, $email_status);
$stmt->execute();
$result = $stmt->get_result();
$exist = $result->num_rows;
if($exist == 1){
?>
<script>
alert("Email already verified.");
window.location = "../public/index.php";
</script>;
<?php exit(); ?>
<?php }else{ ?>
<script>
alert("User not found.");
window.location = "../public/index.php";
</script>;
<?php  }
}else{
$sql = "UPDATE `users` SET `email_status`= ? where `email_token` = ?  LIMIT 1";
$stmt = $conn->prepare($sql);
$stmt->bind_param("ss", $email_status, $token);
$stmt->execute();
$stmt->close();
$_SESSION['msg'] = $msg;
$_SESSION['token'] = $token;
header('Location: mobile_verify.php');
}
}else{
header('Location: index.php');
die();
}
$conn->close();
?>
  1. 通常,您不希望执行"writing"在服务器端处理$_GET请求,但我想象你正在发送电子邮件给用户,他们只是点击一个超链接,所以这是一个可以容忍的场景。
  2. 我不知道您的令牌的加密安全性如何(UUID是一个好主意),但仅依赖一个数据点可能还不够。您可能希望在负载中包含第二个数据点,例如发送到的md5()编码的电子邮件,或者令牌过期的表达式。这些辅助数据点不需要加密安全,但它应该消除意外的数据碰撞或成功的野蛮力攻击。
  3. 我建议你的回复不要给出太多关于失败结果的细节。提供这些类型的线索将比你想要的更有利于黑客。

非常简单,执行UPDATE查询,然后根据受影响的行数,在需要的地方重定向。请确保在需要维护会话的每个页面的开始处启动会话。

未经测试的推荐:

$token = $_GET['token'] ?? null;
if ($token) {
require('../private/autoload.php');
$sql = "UPDATE users
SET email_status='active'
WHERE email_status='inactive'
AND email_token=? LIMIT 1";
$stmt = $conn->prepare($sql);
$stmt->bind_param("s", $token);
$stmt->execute();
if ($stmt->affected_rows) {
$_SESSION['msg'] = "Email verified successfully, thank you.";
$_SESSION['token'] = $token; // why store this in the session?
header('Location: mobile_verify.php');
exit();
}
}
// missing or invalid submission
header('Location: index.php');
exit();

建议通过结合两者的各个方面来减少查询的数量。用户不可能是"活跃的"。或";inactive"在同一时间,所以没有必要做两个查询。

第一个查询已经过时了,因为所有信息都包含在第二个查询中。

(请同时阅读原始帖子的评论)

最新更新