如何将用户输入(密码)哈希到数据库,然后在登录期间读取哈希密码?
我认为解决方案是在注册时散列密码,其中密码在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);
}
我先使用数据库。
答案 0 :(得分:14)
您永远不需要取消密码。 cryptographic hash function应该是单向操作。
(正是这就是为什么它被称为哈希而不是加密。如果unhashing密码是你的操作流程中的正常程序,那么它就不会哈希和unhashing,它将加密和解密。因此,哈希与加密是不同的,正是因为不应该发生unhashing。)
哈希提供安全性,因为即使用户设法查看数据库的内容,也无法窃取用户的密码。
当用户注册时,计算其密码的哈希值,将哈希值存储在数据库中,永远忘记密码。
当用户登录时,计算他们输入的密码的哈希值(也忘记密码),看看哈希值是否与数据库中存储的哈希值匹配。
这是大多数网站使用的机制,这正是为什么如果您成功通过“我忘记密码”程序,他们仍然不会显示您的密码:他们不知道没有它;即使他们想要,也无法取回它。相反,他们会向您发送密码重置链接。
至于如何从字符串计算哈希值,interwebz对该问题的答案比比皆是,例如:MD5 (MSDN); SHA-256 (MSDN); SHA-512 (MSDN)
答案 1 :(得分:3)
说到安全性,不要试图重新发明轮子。使用基于Claims的身份验证。
如果您仍然需要管理用户名和密码,请使用基于哈希的消息身份验证代码(HMAC)
我还建议投资一段时间并阅读Enterprise Security Best Practices。已经有更聪明的人解决了这个问题,为什么要重新发明轮子。 .NET拥有所有的好东西。
以下示例:
using System.Security.Cryptography;
using System.Text;
//--------------------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(hmac2));
注意:盐不必保密,可以与散列本身一起存储。它可以提高rainbow table攻击的安全性。 请不要两次发布相同的问题。从here重复。
答案 2 :(得分:1)
使用Microsoft的System.Web.Helpers.Crypto
NuGet程序包。
您对这样的密码进行哈希处理:
var hash = Crypto.HashPassword("foo");
您验证这样的密码:
var verified = Crypto.VerifyHashedPassword(hash, "foo");