2016-10-01 69 views
4

如何散列用戶輸入(密碼)到數據庫,然後在登錄過程中讀取散列密碼?Asp.net MVC - 如何散列密碼

我相信解決辦法是在註冊時散列密碼,密碼保存爲db內的散列。稍後登錄時,它應該取消散列並將其密碼與用戶密碼輸入進行比較。 但我不知道該怎麼做。

我允許密碼在db中擁有nvarchar(MAX),因爲散列密碼通常很長。

 [Required] 
     [StringLength(MAX, MinimumLength = 3, ErrorMessage = "min 3, max 50 letters")] 
     public string Password { get; set; } 

註冊:

 [HttpPost] 
     public ActionResult Register(User user) { 
      if (ModelState.IsValid) { 

         var u = new User { 
          UserName = user.UserName,        
          Password = user.Password 
         }; 

         db.Users.Add(u); 
         db.SaveChanges(); 

        return RedirectToAction("Login"); 
       } 
      }return View();  
     } 

登錄:

public ActionResult Login() { 
     return View(); 
    } 

    [HttpPost] 
    [ValidateAntiForgeryToken] 
    public ActionResult Login(User u) { 
     if (ModelState.IsValid) 
     { 
      using (UserEntities db = new UserEntities()) { 

       //un-hash password? 

       var v = db.Users.Where(a => a.UserName.Equals(u.UserName) && a.Password.Equals(u.Password)).FirstOrDefault(); 
       if (v != null) { 

        return RedirectToAction("Index", "Home"); //after login 
       } 
      } 
     }return View(u); 
    } 

我使用數據庫第一。

+1

你做**不**加密密碼。你哈希他們。 –

+0

@StephenMuecke謝謝!我修好了它。 – Ezony

+1

爲什麼你不使用身份,這將全部開箱即用?如果你想手動做所有這些,然後參考[這個博客](https://crackstation.net/hashing-security.htm) –

回答

12

你應該永遠不需要解開密碼。 A cryptographic hash function應該是單向操作。這提供了更高的安全性,因爲即使用戶能夠查看數據庫的內容,也無法竊取用戶的密碼。

  • 當用戶寄存器,計算其密碼的哈希,哈希存儲在數據庫中,並永遠忘記密碼。

  • 當用戶登錄時,計算他們輸入密碼的哈希值,(忘記密碼太),看看是否哈希存儲在數據庫中的哈希值相匹配。

這是所使用的大多數網站有機制,而這正是爲什麼,如果你成功地經歷了「忘記密碼」過程中,他們將仍不顯示您的密碼:他們不」沒有它;即使他們想要,他們也無法取回。相反,他們會向您發送密碼重置鏈接。

至於如何從一個字符串計算散列,interwebz比比皆是,例如:MD5 (MSDN); SHA-256 (MSDN); SHA-512 (MSDN)

+0

如果我寫「密碼」,它被哈希,我又寫了另一個「密碼」,他們都會有相同的哈希值呢?或者他們每次都得到隨機散列值?如果隨機,那麼在用戶登錄時如何比較密碼?如果不是隨機的,是否有可能竊取用戶散列值並用它登錄(以某種方式繞過/避免散列被盜散列密碼)? – Ezony

+1

@Ezony他們每次都會有相同的散列。這裏很好的答案Mike。 – Jonesopolis

+0

@Ezony他們會有相同的散列。這就是爲什麼你要創建一個只是一串隨機字符的鹽,才能結束。然後你存儲鹽和散列。當他們輸入密碼時,添加salt,然後對其進行哈希以查看它是否與您存儲的鹽漬哈希進行比較。每個密碼都會得到不同的鹽;因此,即使密碼相同,所有哈希值也是唯一的。 – tphx

0

說到安全性,不要試圖重新發明輪子。使用基於Claims的身份驗證。

如果您仍然需要管理用戶名和密碼使用基於散列的消息認證碼(HMAC

我也建議投資某個時候和閱讀Enterprise Security Best Practices。已經有聰明的人解決了這個問題,爲什麼要重新發明輪子。 .NET在那裏有所有的好東西。下面

例子:

//--------------------MyHmac.cs------------------- 
public static class MyHmac 
{ 
    private const int SaltSize = 32; 

    public static byte[] GenerateSalt() 
    { 
     using (var rng = new RNGCryptoServiceProvider()) 
     { 
      var randomNumber = new byte[SaltSize]; 

      rng.GetBytes(randomNumber); 

      return randomNumber; 

     } 
    } 

    public static byte[] ComputeHMAC_SHA256(byte[] data, byte[] salt) 
    { 
     using (var hmac = new HMACSHA256(salt)) 
     { 
      return hmac.ComputeHash(data); 
     } 
    } 
} 



//-------------------Program.cs--------------------------- 
string orgMsg = "Original Message"; 
     string otherMsg = "Other Message"; 


     Console.WriteLine("HMAC SHA256 Demo in .NET"); 

     Console.WriteLine("----------------------"); 
     Console.WriteLine(); 

     var salt = MyHmac.GenerateSalt(); 

     var hmac1 = MyHmac.ComputeHMAC_SHA256(Encoding.UTF8.GetBytes(orgMsg), salt); 
     var hmac2 = MyHmac.ComputeHMAC_SHA256(Encoding.UTF8.GetBytes(otherMsg), salt); 


     Console.WriteLine("Original Message Hash:{0}", Convert.ToBase64String(hmac1)); 
     Console.WriteLine("Other Message Hash:{0}", Convert.ToBase64String(hmac1)); 

注意:鹽不需要保密,而且可以存儲旁邊的散列本身。這是爲了增加從rainbow table攻擊的安全性。 請不要發表兩次相同的問題。從here複製。