C# 由于比较字段,无法存储哈希密码
因此,我试图为我的应用程序建立一个登录系统,当用户进行注册时,我希望他写两次密码,以确认这是正确的密码。如果在注册后我没有散列我的用户密码,注册会顺利运行,但是在散列之后,我会在尝试将它们保存到我的sql数据库时得到一个验证,因为(我认为)它们不再匹配。我需要如何解决这个问题 用户模型C# 由于比较字段,无法存储哈希密码,c#,asp.net,asp.net-mvc,entity-framework,hash,C#,Asp.net,Asp.net Mvc,Entity Framework,Hash,因此,我试图为我的应用程序建立一个登录系统,当用户进行注册时,我希望他写两次密码,以确认这是正确的密码。如果在注册后我没有散列我的用户密码,注册会顺利运行,但是在散列之后,我会在尝试将它们保存到我的sql数据库时得到一个验证,因为(我认为)它们不再匹配。我需要如何解决这个问题 用户模型 using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Linq;
using System.Web;
namespace TimeTrackerProject.Models
{
[Table("Users")]
public class Users
{
[Key]
public int Iduser { get; set; }
[Required(ErrorMessage = "Email is required")]
[RegularExpression(@"^([\w-\.]+)@((\[[0-9]{1,3]\.)|(([\w-]+\.)+))([a-zA-Z{2,4}|[0-9]{1,3})(\]?)$", ErrorMessage = "Please enter valid email.")]
public String Email { get; set; }
[Required(ErrorMessage = "Firstname is required")]
public String Firstname { get; set; }
[Required(ErrorMessage = "Surname is required")]
public String Surname { get; set; }
[Required(ErrorMessage = "Password is required")]
[DataType(DataType.Password)]
public String Password { get; set; }
[Compare("Password", ErrorMessage = "Please confirm your password")]
[DataType(DataType.Password)]
public String ComfirmPassword { get; set; }
[Required(ErrorMessage = "Function is required")]
public String Function { get; set; }
public Boolean Active { get; set; }
[ForeignKey("RoleId")]
public virtual Roles role { get; set; }
public int? RoleId { get; set; }
}
}
加密类
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Text;
namespace TimeTrackerProject
{
public static class Crypto
{
public static string Hash(string value)
{
return Convert.ToBase64String(
System.Security.Cryptography.HMACSHA256.Create().ComputeHash(Encoding.UTF8.GetBytes(value))
);
}
}
}
注册控制器方法
public ActionResult Register(Users account)
{
if (ModelState.IsValid)
{
account.Password = Crypto.Hash(account.Password);
account.ComfirmPassword = Crypto.Hash(account.ComfirmPassword);
using (TimeTrackerEntities db = new TimeTrackerEntities())
{
db.Users.Add(account);
db.SaveChanges();
}
ModelState.Clear();
ViewBag.Message = account.Firstname + " was successfully registered.";
}
return View();
}
编辑:
我得到的验证是:System.Data.Entity.Validation.DbEntityValidationException:一个或多个实体的验证失败您错误地使用了ASP.NET MVC
您正在设计的模型是一个UI模型—一个
视图模型
,一个数据传输对象
。选择:它符合以下特定标准:
- 模型的存在是为了向用户展示和获取数据李>
- 模型间接地表示数据库级数据李>
- 该模型表示数据的传输李>
ViewModel
/DTO
将数据从数据库传输到用户,或者反过来。ViewModel
/DTO
仍然可以有验证注释,并且仍然可以做与常规模型相同的事情,但是我们不会将从UI获取的模型直接传输到数据库,而是将其放在表示实际数据库记录的常规模型中
如果您查看基本的ASP.NET MVC模板,您将看到以下实际操作:
公共类应用程序用户:IdentityUser
{
}
公共类RegisterViewModel
{
[必需]
[电邮地址]
[显示(Name=“电子邮件”)]
公共字符串电子邮件{get;set;}
[必需]
[StringLength(100,ErrorMessage={0}的长度必须至少为{2}个字符。”,MinimumLength=6)]
[数据类型(数据类型.密码)]
[显示(Name=“密码”)]
公共字符串密码{get;set;}
[数据类型(数据类型.密码)]
[显示(Name=“确认密码”)]
[比较(“密码”,ErrorMessage=“密码和确认密码不匹配。”)]
公共字符串ConfirmPassword{get;set;}
}
[HttpPost]
[异名]
[ValidateAntiForgeryToken]
例如,公共异步任务)为您管理A»B中的映射。什么异常?请将您的问题包括在相关信息中。您的数据模型中没有ComfirmPassword
属性。该属性仅在视图模型中显示。如果不想知道问题所在,请阅读异常。而且此外,您不必比较散列密码,只需比较明文密码即可。不要重新发明身份验证轮子,使用安全、经过良好测试的库。为什么要同时存储密码
和确认密码
(无论是否散列)?比较操作是UI功能,如果两者匹配,则可以存储该密码的单个哈希。这还有助于识别第二个可能的问题:不要将数据库模型对象用于UI,为UI使用一个单独的视图模型对象,其中有许多相同的字段,但视图模型对象有两个密码字段,而数据库模型对象只有一个。@pedroopes请不要使用您自己的加密。使用内置的库…哇,谢谢你的解释,我明白我现在做错了什么。将修改我的代码来实现这一点,谢谢!
public class ApplicationUser : IdentityUser
{
}
public class RegisterViewModel
{
[Required]
[EmailAddress]
[Display(Name = "Email")]
public string Email { get; set; }
[Required]
[StringLength(100, ErrorMessage = "The {0} must be at least {2} characters long.", MinimumLength = 6)]
[DataType(DataType.Password)]
[Display(Name = "Password")]
public string Password { get; set; }
[DataType(DataType.Password)]
[Display(Name = "Confirm password")]
[Compare("Password", ErrorMessage = "The password and confirmation password do not match.")]
public string ConfirmPassword { get; set; }
}
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Register(RegisterViewModel model)
{
if (ModelState.IsValid)
{
// Build an `ApplicationUser` (database model) out of the `RegisterViewModel`
var user = new ApplicationUser { UserName = model.Email, Email = model.Email };
var result = await UserManager.CreateAsync(user, model.Password);
if (result.Succeeded)
{
await SignInManager.SignInAsync(user, isPersistent:false, rememberBrowser:false);
return RedirectToAction("Index", "Home");
}
AddErrors(result);
}
// If we got this far, something failed, redisplay form
return View(model);
}