2017-08-07 6 views
-3

私は自分のアプリケーションのログインシステムを作ろうとしていますが、ユーザーが登録を行っている間にパスワードを2回書いて正しいパスワードであることを確認します。登録後にユーザーパスワードをハッシュしないと、登録はスムーズに実行されますが、ハッシュした後、SQLデータベースに保存しようとしている間に例外が発生します。どのように私はこの問題に対処する必要がありますか?比較フィールドのために暗証番号がハッシュされているパスワード

ユーザーモデル

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

EDITは:exeptionイムが取得 は次のとおりです。System.Data.Entity.Validation.DbEntityValidationException:検証は、1つのまたは複数のエンティティ

+1

** **例外は何ですか?あなたの質問を編集して関連情報を含めてください。 –

+1

データモデルに 'ComfirmPassword'プロパティがありません。そのプロパティはビューモデルのみになります –

+2

問題がどこにあるのか推測しないで、例外を読んでください。また、[HMAC自体は安全なパスワードハッシュ関数ではありません](https://security.stackexchange.com/questions/29951/salted-hashes-vs-hmac)。また、ハッシュされたパスワードを比較する必要はなく、単純に平文のパスワードを比較することもできます。認証ホイールを再作成せず、十分にテストされた安全なライブラリを使用してください。 – CodeCaster

答えて

1

あなたは間違ってASP.NET MVCを使用しているために失敗しました。 View ModelData-Transfer Object -


あなたが設計しているモデルは、UIモデルです。あなたの選択をしてください:それはこの特定の基準に合っています:

  • モデルは、ユーザーからデータを提示して取得するために存在します。
  • モデル間接的には、データベースレベルのデータを表します。
  • このモデルはの転送のデータを表します。

一般的にASP.NET MVCで私たちはViewModel/DTOユーザー、または他の方法で回避し、データベースからデータを転送するために使用するという考えのまわりのものを設計します。 ViewModel/DTOは引き続き検証アノテーションを持つことができますが、それでも通常のモデルと同じことを実行できますが、というモデルをUIからデータベースに直接転送する代わりに、Model実際のデータベースレコードを表します。

あなたは基本的なASP.NET MVCテンプレートを見れば、あなたはこの正確な実際のアクションで表示されます:

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

をそれでは、私たちはここを参照してくださいすることは、設計者は2を構築していることです(DbContextの一部であり、データベースにマッピングされる)RegisterViewModelDbContextのの部分ではなく、であり、クライアントからのデータの要求にのみ使用されます)。

は今、これは必ずしも直感的ではなく、(Add » Viewのような)基本的な行動の多くは、それが間違って取得する(彼らは自動的にDbContextに物事を追加する)が、これは、それを管理するための最も効果的な方法です。

だからあなたの場合には、あなたはおそらく同じ構造を作成したい:(ViewModel/DTOの違いは唯一大会の一つであるRegisterViewModelまたはRegisterDTOを構築し、その後、Userモデルを構築:ViewModelは自明であり、DTOです単に「データ転送オブジェクト」)。


自由側-注意点として:私は、多くの場合、あなたが同じことを行うことができ、そこから自分自身をパラメータとしてデータベースモデルを取るとビルドViewModel/DTOコンストラクタを構築し、必要に応じて、周りに他の道を行く、または何らかの「マッパー」(例えば'Automapper'のような)を使ってA » Bからのマッピングを管理してください。

+0

すてきな説明に感謝しています。私は今何が間違っていたのか理解しています。これを実装するために私のコードを改訂しますありがとう! –

関連する問題