2010-05-01 39 views
5

Bien, estoy un poco atascado en la forma de resolver este problema.ASP MVC: Verificación de correo electrónico (cifrar el enlace de activación)

Cuando un usuario se registra. Quiero enviarle un enlace para que pueda verificar su dirección de correo electrónico.

Pero tengo problemas para generar el enlace.

Ya he escrito el controlador para aceptar los enlaces con las claves correctas. solo no tengo idea de cómo generar las claves de activación.

Así, cuando el usuario se registra lo voy a enviar un enlace por correo así:

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

Ahora he creado este método (llamado por el controlador/acción) para manejar la llave en el enlace:

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

Ahora mi problema es que no tengo idea de cómo cifrar y descifrar el correo electrónico en una especie de llave (URL amigable), así que puede enviarla por correo con el enlace y puede utilizarlo para comprobar el correo electrónico.

Necesito algún tipo de forma (no complicada pero segura) de encriptar el correo electrónico en una clave urlfriendly.

tyvm

Respuesta

3

La forma en que lo haría esto es simplemente generar un largish- random number de la "llave" y luego almacenar una asignación en su base de datos entre la llave de activación y de correo electrónico.

5

Puede ser más fácil no usar ningún cifrado y hacer las cosas un poco más simples.

Crear un nuevo GUID para el enlace (y guardar esto con el usuario), entonces verificar al usuario cuando el enlace se llama

+0

este es el método más fácil en mi opinión –

+1

Si he entendido bien, la versión de Nathan no necesita ahorrar para el usuario. Entonces me parece más simple agregar 2 funciones, que cambiar la base de datos. –

16

Usted podría utilizar algo como Rijndael encryption para cifrar dirección de correo electrónico del usuario como la verificación clave, luego cuando hacen clic en el enlace, simplemente descifrar el código de verificación con su clave de cifrado privada para recuperar la dirección de correo electrónico y activar el usuario adecuado. Con esta técnica, no necesitaría almacenar ningún dato adicional sobre el usuario para la activación de la cuenta y aún tendría un valor encriptado y muy difícil de adivinar como código de verificación.

Aquí hay un ejemplo de Rijndael encryption with C#.

En caso de que no esté familiarizado con él, con el cifrado Rijndael tiene una clave privada que solo usted conoce, que se utiliza como clave de cifrado para sus datos. Siempre que conozca la clave de cifrado siempre puede descifrar lo que haya cifrado.

La belleza adicional de esta técnica es que también hace que sea fácil tener un enlace que expira. Digamos, por ejemplo, que quiere un enlace de restablecimiento de contraseña de 24 horas, por lo que envía al usuario un enlace con un código de verificación, pero en lugar de almacenar datos sobre el código de verificación y su fecha de caducidad en su sistema, cifre el correo electrónico del usuario y una fecha de vencimiento y enviarlo como el código de verificación. Entonces, básicamente, podría cifrar un valor como, 1272746267|14, donde la primera parte es la marca de tiempo de expiración del enlace y el segundo valor es la identificación del usuario en el sistema. Al descifrar y analizar la marca de tiempo, puede tomar la decisión allí mismo, independientemente de si el enlace sigue siendo válido. El único inconveniente que veo en este enfoque es posiblemente la longitud de la cadena encriptada, pero ver como la estás enviando en un correo electrónico que no debería importar demasiado.

Aquí está un ejemplo rápido:

Key: a1b2c3d4e5f6h7i8 
Value: 1272746267|14 

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

Asegúrese de tirar una Url.Encode() en el valor cifrado antes de su vinculación, ya que puede contener algunos personajes antipáticos como barras.

+0

El valor encriptado de ejemplo que usted dio contiene caracteres que no son válidos para poner como parámetro en mi url? estoy pensando en los cortes? –

+0

Actualicé mi publicación y modifiqué el ejemplo para demostrar el cifrado de un valor menos detallado como una indicación de fecha y hora y una identificación de usuario. En lo que respecta a los caracteres en el valor cifrado, simplemente llame a Url.Encode() en el valor antes de incluirlo en el correo electrónico. –

+0

¡Bueno! ¿Hay alguna manera de detectar si el correo electrónico de verificación se ha reenviado a otro usuario? Necesito asegurarme de que quien hace clic en el enlace es mi usuario objetivo y no otro usuario con otro correo electrónico para evitar que los usuarios compartan la contraseña. –

0

Esto es lo que uso. Corto y fácil.

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

El resultado es el siguiente: 8e85a8a078884bbc

0

cifrar, descifrar usando un algoritmo AES. Por favor, encontrar el siguiente ejemplo:

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; 

     } 
    } 
Cuestiones relacionadas