0

这个过程非常简单。

用户填写注册字段后,mysql数据库表中的一列即'activation_key'保持随机生成的长字符串,另一列即activated保持值为0。

激活电子邮件将发送到注册人的电子邮件,其中包含该列的随机键值的激活链接activation_key。单击该链接后,该 url 会在数据库中搜索包含长字符串的activation_key'列。如果有任何此类值,则“activation_key”设置为空白,“激活”列设置为 1。.

当生成激活密钥字符串时,会进行搜索以查看正在生成的密钥是否已经存在,如果存在,则生成另一个随机值以获得唯一的。

因此,当一些潜在成员的注册待定时,实际上会在表中的行上执行类似的字符串搜索。

至此,一切正常。

但是想想一个新成员获得了一个激活字符串,该字符串之前是为另一个完成注册的成员生成的。

万一已经注册的会员点击了旧邮箱中的激活链接,那么其他新会员即使实际上没有完成注册,也会完成注册。

所以我决定不将“activation_key”表设置为空白,因此对所有已经或可能成为成员的成员进行了类似的字符串搜索。

那也行。但是如果用户数量很大,即超过 1 lac,那么发送激活电子邮件的注册过程将花费很多时间。

1)任何其他方式来最小化数据库探索成本?

2) 在这种情况下,像 facebook 这样的大型网站采取什么政策?

4

3 回答 3

2

两次生成相同的激活密钥的机会应该很小。但解决方案是在电子邮件中发送激活密钥和用户名,并对照两者检查数据库。

因此,当激活电子邮件发出时,它包含一个链接

/activate.php?activation_key=key&username=name

而不仅仅是activation_key. 在检查密钥是否真实时,您可以

WHERE activation_key = key AND username = name;

在 mysql 查询中。

因此,通过这种方式,您可以保护系统,以便正确激活用户需要用户名和密钥。

为确保更安全,您可以对列进行UNIQUE索引。activation_key当脚本尝试使用已经存在的键将生成的键添加到用户的行时,查询执行将失败,因为该列被设置为唯一。然后您只需要修改脚本以尝试生成密钥,直到它成功存储在数据库中。确保不要让它无限循环。

无限循环保护

$count = 0;
while ( $errno === 0 )
{
    // mySQL query here
    $errno = mysql_errno();

    $count++;

    if ( $count >= 5 )
            $errno = -1;
}

if ( $errno === -1 )
    echo "Sorry, the script was unable to generate the token for your activation.";

此循环将运行您放置在那里的查询(将激活令牌添加到数据库),直到查询执行没有错误。随着每次执行$count的增加,如果达到限制(示例中为 5),它将强制循环结束(设置$errno为非零但不是真正的 mySQL 错误值),然后向用户显示错误消息.

于 2012-06-02T12:27:43.917 回答
0

在激活链接中包括用户 ID,可能还包括电子邮件地址或用户名。可能的优势:

  • 您可以对用户 ID 进行整数搜索
  • 您无需担心重复的激活链接
  • 您不需要索引activation_key 字段,因为无论如何您都不会搜索它
  • 包含电子邮件(或用户名)时,没有人能够“尝试”所有用户 ID 以激活那些具有 activation_key 副本的用户
  • 暴力破解activation_keys来激活所有用户将非常困难或不可能。
  • 您不必担心activation_key 上的数据竞争。

重要提示:不要只使用电子邮件地址和简短的activation_key。确保几乎不可能暴力破解某个电子邮件地址的激活密钥。

于 2012-06-02T12:31:30.473 回答
0

将新注册和未激活帐户的数据存储在单独的表中。

由于您可能不需要更多关于非活动用户的基本信息,因此您可以保留不必要的数据,例如配置文件设置。

发送激活密钥后,请检查此表以获取具有相应密钥的条目。如果找到,则将日期转移到真实用户表,并从表中删除等待激活的用户的条目。

通过这种方式,您可以:a) 节省空间,因为激活的用户不再需要密钥 b) 更快地了解尚未激活的用户。

在我看来,您还应该将它与删除 3 天左右未激活的用户的 cron 结合起来;-)

于 2012-06-02T12:19:29.813 回答