2010-05-01 14 views
5

Được rồi, tôi đang gặp một chút khó khăn về cách giải quyết vấn đề này.ASP MVC: Xác minh E-mail (Mã hóa liên kết kích hoạt)

Khi người dùng đăng ký. Tôi muốn gửi cho anh ta một liên kết để anh ấy có thể xác minh địa chỉ email của anh ấy.

Nhưng tôi gặp sự cố khi tạo liên kết.

Tôi đã viết bộ điều khiển để chấp nhận các liên kết bằng các phím chính xác. tôi chỉ không có ý tưởng về cách tạo ra các khóa kích hoạt.

Vì vậy, khi đăng ký sử dụng tôi sẽ gửi cho anh ta một liên kết qua đường bưu điện như thế này:

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

Bây giờ tôi đã tạo ra phương pháp này (gọi tắt là bởi bộ điều khiển/hành động) để xử lý là chìa khóa trong liên kết:

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

Bây giờ vấn đề của tôi là tôi không có ý tưởng về làm thế nào để mã hóa và giải mã email vào một số loại chìa khóa (url thân thiện) Vì vậy, tôi có thể gửi nó với các liên kết và có thể sử dụng nó để kiểm tra email.

Tôi cần một số loại (không phức tạp nhưng bảo mật) để mã hóa email thành một khóa thân thiện.

Tyvm

Trả lời

3

Con đường tôi sẽ làm điều này chỉ đơn giản là tạo ra một largish- random number cho "chìa khóa" và sau đó lưu trữ một ánh xạ trong cơ sở dữ liệu của bạn giữa các mã khóa kích hoạt và email.

5

Nó có thể dễ dàng hơn để không sử dụng bất kỳ mã hóa và làm cho mọi thứ đơn giản hơn một chút.

Tạo một Guid mới cho liên kết (và tiết kiệm này với người sử dụng) sau đó chỉ cần xác minh người dùng khi liên kết được gọi là

+0

đây là phương pháp dễ nhất theo ý kiến ​​của tôi –

+1

Nếu tôi hiểu đúng, phiên bản của Nathan không cần lưu cho người dùng. Vì vậy, nó có vẻ đơn giản hơn với tôi để thêm 2 chức năng, hơn là thay đổi DB. –

16

Bạn có thể sử dụng giống như Rijndael encryption để mã hóa địa chỉ e-mail của người dùng như việc xác minh , sau đó khi họ nhấp vào liên kết, bạn chỉ cần giải mã mã xác minh bằng khóa mã hóa riêng của bạn để truy xuất địa chỉ e-mail và kích hoạt người dùng thích hợp. Với kỹ thuật này, bạn sẽ không cần lưu trữ bất kỳ dữ liệu bổ sung nào về người dùng để kích hoạt tài khoản và bạn vẫn có giá trị được mã hóa, rất khó đoán là mã xác minh.

Dưới đây là ví dụ về Rijndael encryption with C#.

Trong trường hợp bạn không quen thuộc với nó, với mã hóa Rijndael bạn có một khóa riêng mà chỉ bạn biết, được sử dụng làm khóa mã hóa cho dữ liệu của bạn. Miễn là bạn biết khóa mã hóa, bạn luôn có thể giải mã mọi thứ bạn đã mã hóa.

Vẻ đẹp bổ sung của kỹ thuật này là nó cũng giúp dễ dàng có liên kết hết hạn. Ví dụ: bạn muốn liên kết đặt lại mật khẩu 24 giờ, do đó bạn gửi cho người dùng liên kết có mã xác minh trong đó, thay vì lưu trữ dữ liệu về mã xác minh và ngày hết hạn trong hệ thống của bạn, hãy mã hóa email của người dùng và ngày hết hạn và gửi đó làm mã xác minh. Về cơ bản, bạn có thể mã hóa một giá trị như, 1272746267|14 trong đó phần đầu tiên là dấu thời gian hết hạn liên kết và giá trị thứ hai là ID của người dùng trong hệ thống. Khi giải mã và phân tích cú pháp dấu thời gian, bạn có thể đưa ra quyết định ngay tại đó cho dù liên kết vẫn hợp lệ hay không. Hạn chế duy nhất tôi nhìn thấy cách tiếp cận này có thể là độ dài của chuỗi được mã hóa, nhưng nhìn thấy khi bạn đang gửi nó trong một e-mail mà không nên quan trọng quá nhiều.

Dưới đây là một ví dụ nhanh:

Key: a1b2c3d4e5f6h7i8 
Value: 1272746267|14 

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

Hãy chắc chắn để ném một Url.Encode() trên giá trị được mã hóa trước khi liên kết nó, vì nó có thể chứa một số ký tự không thân thiện như dấu gạch chéo.

+0

Giá trị được mã hóa ví dụ mà bạn đã cung cấp chứa các ký tự không hợp lệ để đặt làm thông số trong url của tôi? Tôi đang nghĩ đến các dấu gạch chéo ?. –

+0

Tôi đã cập nhật bài đăng của mình và sửa đổi ví dụ để chứng minh mã hóa một giá trị ít tiết hơn như dấu thời gian và ID người dùng. Theo như các ký tự trong giá trị được mã hóa có liên quan, chỉ cần gọi Url.Encode() trên giá trị trước khi bạn bao gồm nó trong e-mail. –

+0

Tốt nhất! Có cách nào để phát hiện xem email xác minh đã được chuyển tiếp đến người dùng khác chưa? Tôi cần đảm bảo rằng người nhấp vào liên kết là người dùng mục tiêu của tôi không phải người dùng khác có email khác để tôi có thể ngăn người dùng chia sẻ mật khẩu. –

0

Đây là những gì tôi sử dụng. Ngắn gọn và dễ dàng.

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); 
} 

quả trông như thế này: 8e85a8a078884bbc

0

Encrypt, Decrypt sử dụng AES. Vui lòng tìm ví dụ bên dưới:

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; 

     } 
    } 
Các vấn đề liên quan