程序:网站帐户激活(撤销)系统

用户注册你的网站时,要确认他们提供了一个正确的email地址,这会很有帮助。要验证用户提供的email地址,可以向他们注册时提供的地址发送一个email。如果他们几天后仍未访问email中包含的特殊URL,则撤销他们的帐户。
这个系统包括3个部分。
第一部分是notify-user,php程序,它向新用户发送一个email,并要求用户访问一个验证URL。
第二部分verify-user.php页面,用来处理验证URL,并标志用户为合法用户。
第三部分delete-user.php程序,如果用户在一定时间内没有访问验证URL则撤销这个用户的帐户。

创建数据库表的SQL,将在这个表中存储用户信息。
-- 创建一个名为users的表,用于存储用户信息
CREATE TABLE users(
-- email字段,用于存储用户的电子邮件地址
email VARCHAR(255) NOT NULL, -- VARCHAR(255)表示这是一个可变长度的字符串,最大长度为255个字符。NOT NULL表示该字段在创建记录时必须有值,不能为空。

-- created_on字段,用于记录用户账户创建的时间
created_on DATETIME NOT NULL, -- DATETIME类型用于存储日期和时间值。NOT NULL同样表示该字段在创建记录时必须有值。

-- verify_string字段,用于存储验证字符串,通常用于电子邮件验证或密码重置流程
verify_string VARCHAR(16) NOT NULL, -- VARCHAR(16)表示这是一个可变长度的字符串,最大长度为16个字符。这里存储的验证字符串可能是一个哈希值或随机生成的代码。NOT NULL意味着这个字段在创建记录时必须被赋值。

-- verified字段,用于标记用户是否已经验证了他们的电子邮件地址或其他验证流程
verified TINYINT UNSIGNED -- TINYINT是一个整数类型,用于存储非常小的数值。UNSIGNED关键字表示这个字段只能存储非负整数(即0或正整数)。在这个上下文中,它可能被用作一个布尔标志(尽管不是严格的布尔类型),其中0可能表示未验证,而任何非零值表示已验证。通常,为了清晰起见,可能会使用1表示已验证,但这不是强制的。

);

notify-user.php

// 创建一个新的 PDO 实例,用于连接到 SQLite 数据库文件 'users.db'
$db = new PDO('sqlite:users.db');

// 设置一个电子邮件地址变量,这里以 'david' 作为示例
$email = 'david';

// 初始化一个空字符串,用于存储生成的验证字符串
$verify_string ='';
// 使用 for 循环生成一个长度为 16 的随机字符串,每个字符的 ASCII 码在 32 到 126 之间
// 这通常对应可打印的 ASCII 字符,不包括控制字符
for($i = 0; $i < 16; $i++){
$verify_string .= chr(mt_rand(32,126));
}

// 准备一个 SQL 语句,用于向 'users' 表中插入新用户的数据
// 使用预处理语句可以防止 SQL 注入攻击
$str = $db->prepare("INSERT INTO users ".
"(email, created_on, verify_string, verified) " .
"VALUES(?, datetime('now'), ?, 0)");
// 执行预处理语句,绑定参数为用户提供的电子邮件和生成的验证字符串
// 'datetime('now')' 是 SQLite 的一个函数,用于获取当前日期和时间
$str->execute(array($email, $verify_string));

// 对验证字符串和电子邮件地址进行 URL 编码,以确保它们可以安全地作为 URL 的一部分
$verify_string = urlencode($verify_string);
$safe_email = urlencode($email);

// 设置验证链接的基础 URL
$verify_url = "http://www.example.com/verify-user.php";

// 使用 heredoc 语法创建一个邮件正文字符串
// heredoc 允许在 PHP 中定义多行字符串
$mail_body=<<<MAIL
To $email:
please click on the following link to verify your account creation:
$verify_url?email=$safe_email&verify_string=$verify_string
If you do not verify your account in the next seven days, it will be deleted.
MAIL

// 使用 PHP 的 mail() 函数发送邮件
// 第一个参数是收件人的电子邮件地址
// 第二个参数是邮件的主题
// 第三个参数是邮件的正文
// 注意:mail() 函数在发送邮件时并不提供高级功能,如 HTML 格式或附件,且可能需要在服务器上配置 SMTP
mail($email,"User Verification",$mail_body);

verify-user.php
// 初始化一个新的PDO实例,用于连接名为'users.db'的SQLite数据库文件
$db = new PDO('sqlite:users.db');

// 准备一条SQL更新语句,旨在将users表中满足特定条件的用户的verified字段设置为1。
// 条件包括:email字段匹配给定的值、verify_string字段也匹配给定的值,并且verified字段当前为0。
$str = $db->prepare('UPDATE users SET verified = 1 WHERE email = ? AND verify_string = ? AND verified = 0');

// 执行前面准备的SQL语句,参数为一个数组,包含从GET请求中获取的email和verify_string值。
// 注意:直接将$_GET参数用于数据库查询存在安全风险,尽管这里使用了PDO预处理语句(一种防止SQL注入的有效手段),
// 但最佳实践仍是对所有外部输入进行验证和清理。
$res = $str->execute(array($_GET['email'], $_GET['verify_string']));

// 使用var_dump函数输出执行结果和受影响的行数,便于调试。
// $res为布尔值,表示执行是否成功;$str->rowCount()返回受影响的行数。
var_dump($res, $str->rowCount());

// 判断SQL语句执行是否成功
if(!$res){
// 若执行失败,则输出错误信息,提示用户稍后再试。
print "Please try again later due to a database error.";
}else{
// 若执行成功,则进一步检查受影响的行数
if($str->rowCount() == 1){
// 若正好有一行数据被更新,说明验证成功,向用户表示感谢并通知其账户已验证。
print "Thank you, your account is verified.";
}else{
// 若没有行被更新(可能是提供的email或verify_string不匹配,或该用户已验证),
// 则输出一个较为模糊的消息,这可能给用户带来困惑。
// 建议改进消息内容,以更准确地反映验证失败的原因。
print "Sorry, you could be verified.";
}
}

delete-user.php
// 创建一个新的PDO实例,用于连接SQLite数据库。这里数据库文件名为'users.db'。
$db = new PDO('sqlite:users.db');

// 定义一个时间窗口变量,表示从当前时间往回算的7天。
$window = '-7 days';

// 准备一个SQL语句,用于删除那些未验证(verified字段值为0)且创建时间(create_on字段)早于当前时间减去7天的用户。
// 注意:这里使用了SQLite的datetime函数和参数绑定来避免SQL注入攻击。
$sth = $db->prepare("DELETE FROM users WHERE verified = 0 AND ".
" create_on < datetime('now',?)");

// 执行准备好的SQL语句,将$window变量的值(即'-7 days')作为参数传递给SQL语句中的问号占位符。
// execute方法返回一个布尔值,表示执行是否成功。
$res = $sth->execute(array($window));

// 根据执行结果,输出相应的信息。
if($res){
// 如果执行成功,使用rowCount()方法获取受影响的行数(即被删除的用户数量),并打印出来。
// 注意:对于DELETE语句,不是所有的数据库驱动都支持rowCount()方法返回被影响的行数。
// 在SQLite中,如果使用了LIMIT或OFFSET,或者在执行后没有使用其他查询,rowCount()可以返回被删除的行数。
print "Deactivated " . $sth->rowCount() . " users.";
}else{
// 如果执行失败,打印错误信息。
print "Can't delete users.";
}

posted @   kksllss  阅读(7)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· 没有源码,如何修改代码逻辑?
· PowerShell开发游戏 · 打蜜蜂
· 在鹅厂做java开发是什么体验
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战
点击右上角即可分享
微信分享提示