ASP MVC:电子邮件验证(加密激活链接)

时间:2010-05-01 11:43:34

标签: c# asp.net asp.net-mvc email encryption

好吧,我有点担心如何解决这个问题。

当用户注册时。我想给他发一个链接,以便他可以验证他的电子邮件地址。

但我有麻烦产生链接。

我已经编写了控制器来接受带有正确密钥的链接。我根本不知道如何生成激活密钥。

因此,当用户注册时,我将通过邮件向他发送链接,如下所示:

Your activation link is : http://site.com/user/verify?key=keyhere

现在我创建了这个方法(由控制器/动作调用)来处理链接中的键:

 public string Verify(string value)
    {
        String email = Decrypt(value);

        user u = gebRep.GetUsers().WithEmail(email).SingleOrDefault();
        if (u != null)
        {
            u.emailValid = true;
            userReppository.Save();
        }

        return "Invallid validation value!";
    }

现在我的问题是我不知道如何加密和解密电子邮件到某种键(友好的网址)所以我可以用链接邮寄它,并可以用它来验证电子邮件。

我需要某种(不是复杂但安全的)方式将电子邮件加密到urlfriendly键。

Tyvm

5 个答案:

答案 0 :(得分:16)

您可以使用类似Rijndael encryption的内容来加密用户的电子邮件地址作为验证密钥,然后当他们点击链接时,您只需使用私有加密密钥解密验证码以检索电子邮件地址并激活适当的用户。使用这种技术,您不需要存储有关用户的任何额外数据以进行帐户激活,并且您仍然需要加密,非常难以猜测的值作为验证码。

以下是Rijndael encryption with C#的示例。

如果您不熟悉它,使用Rijndael加密,您将拥有一个只有您知道的私钥,该私钥用作数据的加密密钥。只要您知道加密密钥,您就可以随时解密所有加密密钥。

这项技术的另一个优点是它也可以轻松实现过期链接。比如说你想要一个24小时密码重置链接,所以你向用户发送一个包含验证码的链接,而不是在你的系统中存储有关验证码及其截止日期的数据,加密用户的电子邮件和到期日期并将其作为验证码发送。所以基本上,您可以加密一个值,例如1272746267|14,其中第一部分是链接到期时间戳,第二个值是系统中用户的ID。在解密和解析时间戳时,您可以在那里做出决定,无论链接是否仍然有效。我看到这种方法的唯一缺点可能是加密字符串的长度,但看到你在电子邮件中发送它并不重要。

这是一个简单的例子:

Key: a1b2c3d4e5f6h7i8
Value: 1272746267|14

Encrypted: wxtVC1u5Q7N9+FymCln3qA==
Decrypted: 1272746267|14

确保在链接之前在加密值上抛出Url.Encode(),因为它可能包含一些不友好的字符,如斜杠。

答案 1 :(得分:5)

可能更容易不使用任何加密并使事情变得更简单。

为链接创建一个新的Guid(并将其与用户保存)然后只需在调用链接时验证用户

答案 2 :(得分:3)

我这样做的方法就是为“密钥”生成一个较大的 - random number,然后在激活密钥和电子邮件之间存储数据库中的映射。

答案 3 :(得分:0)

这就是我使用的。简单易行。

private string GetNewValidationCode()
{
    long i = 1;
    foreach (byte b in Guid.NewGuid().ToByteArray())
    {
        i *= ((int)b + 1);
    }
    return string.Format("{0:x}", i - DateTime.Now.Ticks);
}

结果如下所示:8e85a8a078884bbc

答案 4 :(得分:0)

加密,使用AES解密。请找下面的例子:

class AesExample
    {
        public static void Main()
        {
            try
            {

                string original = "Here is some data to encrypt!";

                // Create a new instance of the AesManaged
                // class.  This generates a new key and initialization 
                // vector (IV).
                using (AesManaged myAes = new AesManaged())
                {

                    // Encrypt the string to an array of bytes.
                    string encrypted = EncryptPasswordAes(original, myAes.Key, myAes.IV);

                    // Decrypt the bytes to a string.
                    string roundtrip = DecryptPasswordAes(encrypted, myAes.Key, myAes.IV);

                    //Display the original data and the decrypted data.
                    Console.WriteLine("Original:   {0}", original);
                    Console.WriteLine("Encrypted: {0}", encrypted);
                    Console.WriteLine("Round Trip: {0}", roundtrip);

                    Console.ReadLine();
                }

            }
            catch (Exception e)
            {
                Console.WriteLine("Error: {0}", e.Message);
            }
        }
        static string EncryptPasswordAes(string plainText, byte[] Key, byte[] IV)
        {
            // Check arguments.
            if (plainText == null || plainText.Length <= 0)
                throw new ArgumentNullException("plainText");
            if (Key == null || Key.Length <= 0)
                throw new ArgumentNullException("Key");
            if (IV == null || IV.Length <= 0)
                throw new ArgumentNullException("Key");
            byte[] encrypted;
            // Create an AesManaged object
            // with the specified key and IV.
            using (AesManaged aesAlg = new AesManaged())
            {
                aesAlg.Key = Key;
                aesAlg.IV = IV;

                // Create a decrytor to perform the stream transform.
                ICryptoTransform encryptor = aesAlg.CreateEncryptor(aesAlg.Key, aesAlg.IV);

                // Create the streams used for encryption.
                using (MemoryStream msEncrypt = new MemoryStream())
                {
                    using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
                    {
                        using (StreamWriter swEncrypt = new StreamWriter(csEncrypt))
                        {

                            //Write all data to the stream.
                            swEncrypt.Write(plainText);
                        }
                        encrypted = msEncrypt.ToArray();
                    }
                }
            }


            // Return the encrypted bytes from the memory stream.
            return Convert.ToBase64String(encrypted);

        }

        static string DecryptPasswordAes(string encryptedString, byte[] Key, byte[] IV)
        {
            //Convert cipher text back to byte array
            byte[] cipherText = Convert.FromBase64String(encryptedString);
            //  Byte[] cipherText = System.Text.Encoding.UTF8.GetBytes(encryptedString);
            // Check arguments.
            if (cipherText == null || cipherText.Length <= 0)
                throw new ArgumentNullException("cipherText");
            if (Key == null || Key.Length <= 0)
                throw new ArgumentNullException("Key");
            if (IV == null || IV.Length <= 0)
                throw new ArgumentNullException("Key");

            // Declare the string used to hold
            // the decrypted text.
            string plaintext = null;

            // Create an AesManaged object
            // with the specified key and IV.
            using (AesManaged aesAlg = new AesManaged())
            {
                aesAlg.Key = Key;
                aesAlg.IV = IV;

                // Create a decrytor to perform the stream transform.
                ICryptoTransform decryptor = aesAlg.CreateDecryptor(aesAlg.Key, aesAlg.IV);

                // Create the streams used for decryption.
                using (MemoryStream msDecrypt = new MemoryStream(cipherText))
                {
                    using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read))
                    {
                        using (StreamReader srDecrypt = new StreamReader(csDecrypt))
                        {

                            // Read the decrypted bytes from the decrypting stream
                            // and place them in a string.
                            plaintext = srDecrypt.ReadToEnd();
                        }
                    }
                }

            }

            return plaintext;

        }
    }