【问题标题】:ASP MVC: E-mail Verification (Encrypting the activation link)ASP MVC:电子邮件验证(加密激活链接)
【发布时间】:2011-02-14 12:57:10
【问题描述】:

好吧,我有点不知道如何解决这个问题。

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

但我无法生成链接。

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

所以当用户注册时,我会通过邮件向他发送一个链接,如下所示:

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!";
    }

现在我的问题是我不知道如何将电子邮件加密和解密为某种密钥(url 友好)所以我可以用链接邮寄它并使用它来验证电子邮件。

我需要某种(不复杂但安全的)方法将电子邮件加密为 urlfriendly 密钥。

Tyvm

【问题讨论】:

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


    【解决方案1】:

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

    【讨论】:

      【解决方案2】:

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

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

      【讨论】:

      • 这是我认为最简单的方法
      • 如果我理解正确的话,Nathan 的版本不需要保存给用户。所以对我来说添加 2 个函数似乎比更改数据库更简单。
      【解决方案3】:

      您可以使用Rijndael encryption 之类的东西来加密用户的电子邮件地址作为验证密钥,然后当他们单击链接时,您只需使用您的私人加密密钥解密验证码即可检索电子邮件地址并激活合适的用户。使用这种技术,您无需存储任何关于用户的额外数据来激活帐户,并且您仍然拥有一个加密的、非常难以猜测的值作为验证码。

      这是Rijndael encryption with C# 的示例。

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

      这种技术的另一个优点是它还可以很容易地拥有一个过期的链接。例如,您想要一个 24 小时密码重置链接,因此您向用户发送一个包含验证码的链接,但不是在系统中存储有关验证码及其到期日期的数据,而是加密用户的电子邮件并到期日期并将其作为验证码发送。所以基本上,你可以加密一个像1272746267|14 这样的值,其中第一部分是链接过期时间戳,第二个值是系统中的用户 ID。在解密和解析时间戳后,您可以在此处做出链接是否仍然有效的决定。我看到这种方法的唯一缺点可能是加密字符串的长度,但是当您在电子邮件中发送它时,这并不重要。

      这是一个简单的例子:

      Key: a1b2c3d4e5f6h7i8
      Value: 1272746267|14
      
      Encrypted: wxtVC1u5Q7N9+FymCln3qA==
      Decrypted: 1272746267|14
      

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

      【讨论】:

      • 您提供的示例加密值包含无法作为参数放入我的网址的字符?我在想斜线?。
      • 我更新了我的帖子并修改了示例以演示加密不太详细的值,例如时间戳和用户 ID。就加密值中的字符而言,只需在将其包含在电子邮件中之前对该值调用 Url.Encode()。
      • 好一个!有什么方法可以检测验证邮件是否已转发给其他用户?我需要确保点击链接的人是我的目标用户,而不是另一个拥有另一封电子邮件的用户,这样我就可以防止用户共享密码。
      • 我不知道怎么联系你,只是想说你的个人资料cv链接坏了。请通知 SO 团队,我认为他们的网址做了一些更改。
      【解决方案4】:

      这是我使用的。简短易懂。

      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

      【讨论】:

        【解决方案5】:

        使用 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;
        
                }
            }
        

        【讨论】:

          猜你喜欢
          • 2014-08-17
          • 2014-03-16
          • 2013-02-17
          • 2015-03-24
          • 2023-03-03
          • 2017-06-22
          • 2014-06-11
          • 2020-04-10
          • 1970-01-01
          相关资源
          最近更新 更多