データベースに保存されているハッシュ化されたパスワードからログイン機能を動かしたい
解決したいこと
現在、ログイン機能(メールアドレスとパスワード記述)を実装しようとしています。
ログイン機能の前に新規登録機能を実装しましたがその際postgres接続でテーブル名は"user"ですがカラムにパスワードがありますが登録時、ハッシュ化しています。
ログイン機能実装時にテキストボックスに記述されたパスワードを取得し、それを新規登録と同じ要領でハッシュ化すればデータベースに登録されているハッシュ化パスワードと一致するので比較してtrueを走らせればよいと考えていましたがハッシュ化された値は違うものでした。
調べると同じパスワードでも違う値を返すこと、ハッシュ化された文字列はもとには戻せないことを知りました。ログイン機能を実装するにはどのようにすればよいですか?
例)
ログインが成功すればページ遷移できる仕様
該当するソースコード
登録機能のコントローラー(アクション名はCreate)
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Threading.Tasks;
using TestWebApplication.Models;
using User.Models;
using MyConnection.Commons;
using Microsoft.Extensions.Configuration;
using Microsoft.AspNetCore.Cryptography.KeyDerivation;
using System.Security.Cryptography;
namespace TestWebApplication.Controllers
{
public class RegistController : Controller
{
public IActionResult Index()
{
return View();
}
[HttpPost] //regist.cshtmlのformタグ内から変数を持ってきている
public IActionResult Create(UserList model)
{
Console.WriteLine(model.Password);
Console.WriteLine(model.ConfirmPassword);
Console.WriteLine(model.MailAddress);
Console.WriteLine(model.Name);
if (ModelState.IsValid)
{
Console.WriteLine("成功!!");
}
else
{
return View("Index");
}
//参考文献https://www.atmarkit.co.jp/fdotnet/dotnettips/977aspmvctempdata/aspmvctempdata.html
byte[] salt = new byte[128 / 8];
using var rng = RandomNumberGenerator.Create();
rng.GetBytes(salt);
byte[] hash = KeyDerivation.Pbkdf2(
model.Password,
salt,
prf: KeyDerivationPrf.HMACSHA256,
iterationCount: 10000, // 反復回数
numBytesRequested: 256 / 8); // ハッシュの長さ
string hashed = string.Concat(hash.Select(b => $"{b:x2}")); //パスワードがハッシュ化された変数 中身3ee3d8d2aaf4b0b2ab82a2b9641442463f8e86eb13794ceed448a804656ccb7d
//データベース接続処理
using var db = new Db();
var newMenber = new UserList { Password = hashed, MailAddress = model.MailAddress, Name = model.Name };
db.Menber.Add(newMenber);
db.SaveChanges();
return RedirectToAction("Index", "Login");
}
}
}
ログイン機能のコントローラー(アクション名はLogin)
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Threading.Tasks;
using TestWebApplication.Models;
using User.Models;
using MyConnection.Commons;
using Microsoft.Extensions.Configuration;
using Microsoft.AspNetCore.Cryptography.KeyDerivation;
using System.Security.Cryptography;
namespace TestWebApplication.Controllers
{
public class LoginController : Controller
{
public IActionResult Index()
{
return View();
}
[HttpPost]
public IActionResult Login(string mail, string password)
{
Console.WriteLine(mail);
Console.WriteLine(password);
using (var context = new Db()) //DbはMyConnectionのクラス名
{
var result = context.Menber.Count(x => x.MailAddress == mail); //MenberはMyConnection.csを参照
if(result == 0)
{
return View("Index");
}
var product = context.Menber.Single(x => x.MailAddress == mail);
Console.WriteLine(product.Name); //同じメールアドレスが存在:それに対応する名前
Console.WriteLine(product.MailAddress); //同じメールアドレスが存在:それに対応するメールアドレス
Console.WriteLine(product.Password); //同じメールアドレスが存在:それに対応するハッシュ化されたパスワード 中身3ee3d8d2aaf4b0b2ab82a2b9641442463f8e86eb13794ceed448a804656ccb7d
byte[] salt = new byte[128 / 8];
using var rng = RandomNumberGenerator.Create();
rng.GetBytes(salt);
byte[] hash = KeyDerivation.Pbkdf2(
password,
salt,
prf: KeyDerivationPrf.HMACSHA256,
iterationCount: 10000, // 反復回数
numBytesRequested: 256 / 8); // ハッシュの長さ
string hashed = string.Concat(hash.Select(b => $"{b:x2}")); //パスワードがハッシュ化された変数 中身16809ac99606ff81e80ab960ceefec321008fa392a4d555ddbe5cddcf7223678
Console.WriteLine(hashed);
return RedirectToAction("Index", "Main");
}
}
}
}
product.Passwordとhashedが一致していれば良かったが上手くいかなかった。(同じパスワード文字列でハッシュ化している)