php 如何在php中生成安全的激活字符串?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/876139/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to generate a secure activation string in php?
提问by St. John Johnson
After user subscribe email to my website. My website will generate an email confirmation and send to them. In the email content, i need to include activation key, something like:
用户订阅电子邮件到我的网站后。我的网站将生成一封电子邮件确认并发送给他们。在电子邮件内容中,我需要包含激活密钥,例如:
www.domain.com/activate.php?key=$generatedKey
www.domain.com/activate.php?key=$generatedKey
How do you generate the key? using sha1($email)??
你如何生成密钥?使用 sha1($email)??
After generate the key, i store it in database, so that when user click the link I can verified it with the database?? I am new to it, please advise.. I need an Email Confirmation script..
生成密钥后,我将其存储在数据库中,以便当用户单击链接时我可以用数据库验证它??我是新手,请指教.. 我需要一个电子邮件确认脚本..
回答by St. John Johnson
Personally, just I use a combination of things like:
就我个人而言,只是我使用了以下内容的组合:
$generatedKey = sha1(mt_rand(10000,99999).time().$email);
The chance of collision is small, but I recommend checking your database first before sending it out (using UNIQUE constraints is an easy way).
冲突的可能性很小,但我建议在发送之前先检查您的数据库(使用 UNIQUE 约束是一种简单的方法)。
回答by St. John Johnson
You basically have a few options:
你基本上有几个选择:
1) Create a single unique identifier that is seemingly random and store it in your database with which username it corresponds to
1)创建一个看似随机的唯一标识符并将其存储在您的数据库中,它对应于哪个用户名
2) Generate a random password and include the user id and password in the link and store the password in the database
2) 生成随机密码并在链接中包含用户名和密码并将密码存储在数据库中
3) Use a one way hashing function (md5, sah1, etc) and a secret identifier to encrypt the user identifier. You don't have to store the encrypted user identifier in your database.
3) 使用单向散列函数(md5、sah1 等)和秘密标识符来加密用户标识符。您不必将加密的用户标识符存储在您的数据库中。
Option 1 is difficult because you have to worry about checking the database to see if the key already exists. However, it is nice that the URL does not contain the username being activated.
选项 1 很困难,因为您必须担心检查数据库以查看密钥是否已存在。但是,该 URL 不包含被激活的用户名是件好事。
If you are already going to use some sort of database to store the user information (probably a password at minimum) in the future, you could go with option 2. It doesn't take a lot to add another column to your database. When sending the email, save the username and something like $key = sha1(rand(1, 99999) . $username) in another column for the row that contains the username. Then have your link look like this: http://you.com/activation.php?user=$username&key=$key. In activation.php you check to see if the key is equal to the value stored in the database.
如果您将来已经打算使用某种数据库来存储用户信息(至少可能是密码),您可以选择选项 2。将另一列添加到您的数据库中不需要太多。发送电子邮件时,在包含用户名的行的另一列中保存用户名和类似 $key = sha1(rand(1, 99999) . $username) 的内容。然后让你的链接看起来像这样:http: //you.com/activation.php?user= $username&key=$key。在 activation.php 中,您检查密钥是否等于存储在数据库中的值。
If you want to use less storage space in your database, option 3 will work. You can use something like $key = sha1($mysecret . $username) as the secret identifier. Use something odd that only you know as $mysecret such as 'aaafj_my_secret_adfaf'. Use the same type of URL as in option 2. However, because you can generate $key based only on $username, you don't need to store it. So when you are processing in activation.php, just check to see if sha1($mysecret . $_GET[username]) == $_GET[key]. If it does, you know you have the correct user. Theoretically, with enough registrations, someone could figure out your value for $mysecret and generate the activation keys too. However, you would surely notice the billions or more of registrations that it would take before they could begin to calculate what it is. The number of activations required is based on the key size of the hashing function. Use sha1 (160 bit) vs md5 (128 bit) to make it harder to guess your $mysecret value.
如果您想在数据库中使用更少的存储空间,选项 3 将起作用。您可以使用类似 $key = sha1($mysecret . $username) 作为秘密标识符的东西。使用只有您知道的奇怪东西 $mysecret,例如 'aaafj_my_secret_adfaf'。使用与选项 2 中相同类型的 URL。但是,因为您可以仅根据 $username 生成 $key,所以您不需要存储它。所以当你在 activation.php 中处理时,只需检查 sha1($mysecret . $_GET[username]) == $_GET[key]。如果是这样,您就知道您拥有正确的用户。从理论上讲,只要注册足够多,有人就可以计算出 $mysecret 的价值并生成激活密钥。但是,您肯定会注意到在他们开始计算它是什么之前需要进行数十亿次或更多的注册。所需的激活次数取决于散列函数的密钥大小。使用 sha1(160 位)与 md5(128 位)使您更难猜测您的 $mysecret 值。
回答by Eli
If you're storing the activation string in the database and checking it later, you don't need a hash at all!
如果您将激活字符串存储在数据库中并稍后进行检查,则根本不需要散列!
You just need a long, random string. You can generate it however you want, just make it long. In fact, it should ideally have nothing at all do do with the email or username.
你只需要一个长的随机字符串。你可以随心所欲地生成它,只要让它长一点。事实上,理想情况下,它应该与电子邮件或用户名完全无关。
回答by Itay Moav -Malimovka
$guid=md5(uniqid(mt_rand(), true));
回答by Alix Axel
That should do it, however you can improve it by adding some salt, example:
应该这样做,但是您可以通过添加一些盐来改进它,例如:
$key = sha1($email . 'doYouLikeSauce');
Other approach is just to generate a random password and send it via email.
其他方法只是生成一个随机密码并通过电子邮件发送。
回答by Leandros Ioannou
$code = md5($_POST['username'] . microtime());

