Begin your journey by creating an account. Registration is a quick and simple process that opens the door to a world of possibilities.
是日將製作使用者相關之API實務,其含使用者之註冊、使用者之驗證、使用者之登入等,然而在其開始前,將先說明此次之密碼加密實務。
在註冊時,使用者輸入密碼並註冊後,通常情況並不建議以明文儲存密碼,此次實務亦然。以下將介紹此次密碼加密方式,其一,先建立檔案,名「PasswordHelper」,其二如下,其三,於program.cs中註冊,以builder.Services.AddSingleton<PasswordHelper>();
:
private readonly string key;
public PasswordHelper(IConfiguration configuration)
{
// 自行創立之HashKey,於appsettings.json中
key = configuration.GetValue<string>("HashKey");
}
// 進行密碼加密
public string HashPassword(string password)
{
// 將key轉換為 UTF-8 編碼的字節陣列
byte[] keyByte = new UTF8Encoding().GetBytes(key);
byte[] passwordByte = new UTF8Encoding().GetBytes(password);
// 以HMACSHA256加密
using( var hmacSHA256 = new HMACSHA256(keyByte))
{
// 密碼之加密
byte[] hashedPassword = hmacSHA256.ComputeHash(passwordByte);
// 將加密之密碼轉換為十六進制表示形式的字符串
return BitConverter.ToString(hashedPassword).Replace("-", "").ToLower();
}
}
在登入時,使用者輸入密碼並登入後,須將其加密在與資料庫中加密之密碼進行比對:
public bool VerifyPassword (string password, string hashedpassword)
{
if (HashPassword(password).Equals(hashedpassword))
{
return true;
}
return false;
}
因皆為使用者之操作事項,因此將註冊、驗證、登入等寫在同一控制區中,並使用服務區之功能,在Services之資料夾中建立UserService.cs之檔案,並於Program.cs中以builder.Services.AddScoped<UserService>();
進行註冊,並於控制區中啟用該服務,其一為控制區,其二為服務區,以下不再贅述。
[ApiController]
[Route("user")]
public class UserController : ControllerBase
{
private readonly UserService _userService;
public UserController(UserService userService)
{
_userService = userService;
}
}
public class UserService
{
private readonly DnDContext _context;
private readonly IMapper _mapper;
private readonly PasswordHelper _passwordHelper;
public UserService(DnDContext context, IMapper mapper, PasswordHelper passwordHelper)
{
_context = context;
_mapper = mapper;
_passwordHelper = passwordHelper;
}
JsonResult success = new JsonResult(new { status = "註冊成功" });
JsonResult fail = new JsonResult(new { status = "註冊失敗" });
}
許多網站之第一步為註冊帳號,以記錄使用者之資料,並可解鎖許多網站之功能。以下為實務內容:
[HttpPost]
public async Task<IActionResult> Register(RegisterDto register)
{
if (register == null)
{
return BadRequest("檢查輸入資料");
}
var result = await _userService.Register(register);
return result;
}
public async Task<IActionResult> Register(RegisterDto register)
{
// 確認無重複使用者名稱
var user = _context.UserProfile.SingleOrDefault(e => e.Username == register.Username);
if (user != null) return fail;
var profile = new UserProfile()
{
Password = _passwordHelper.HashPassword(register.Password)
};
profile = _mapper.Map(register, profile);
// 新增使用這資訊
var info = new UserInfo()
{
Uuid = profile.Uuid
};
// 新增使用者驗證
var verification = new Verification()
{
Uuid = profile.Uuid,
VerificationCode = new Random().Next(0, 999999),
};
// 傳送驗證碼
var verifyMail = new MailData()
{
Name = profile.Username,
Email = profile.Email,
Subject = "Verify your account",
Body = $"Dear {profile.Username},\n" +
$"This your Verification Code: {verification.VerificationCode}"
};
_mailHelper.SendMail(verifyMail);
_context.AddRange(profile, info, verification);
try
{
await _context.SaveChangesAsync();
}
catch (Exception ex)
{
return fail;
}
return success;
}
註冊完後,通常應驗證使用者之資料是否為本人註冊,或以驗證碼開通帳號之各項功能。以下為實務內容:
[HttpPost("verify")]
public async Task<IActionResult> Verify(int VerificationCode)
{
if(VerificationCode == 0)
{
return BadRequest();
}
var result = await _userService.Verify(VerificationCode);
return result;
}
public async Task<IActionResult> Verify(int VerificationCode)
{
var user = _context.Verifications.Include(e => e.UserProfile).SingleOrDefault(e => e.VerificationCode.Equals(VerificationCode));
if (user == null) return not_found;
user.UserProfile.Verified = true;
_context.UserProfile.Update(user.UserProfile);
try
{
await _context.SaveChangesAsync();
}
catch (Exception ex)
{
return fail;
}
return success;
}
完成註冊,並通過驗證,便可進行登入,登入可以使用者之身分進行各項事務,如創建角色之功能。以下為實務內容,使用者登入後便可獲得bearer Token以便進行驗證、授權:
[HttpPost("login")]
public async Task<IActionResult> Login(LoginDto login)
{
if (login == null)
{
return BadRequest();
}
var result = await _userService.Login(login);
return result;
}
public async Task<IActionResult> Login(LoginDto login)
{
var unverified = new JsonResult(new { status = "unverified" });
var user = _context.UserProfile.SingleOrDefault(e => e.Email.Equals(login.Email));
// 確認使用者存在
if (user == null) return not_found;
// 確認使用者已驗證
if (!user.Verified) return unverified;
// 比對使用者密碼
if (!_passwordHelper.VerifyPassword(login.Password, user.Password)) return fail;
var token = _jwtHelper.GenerateToken(user.Uuid, user.Username, "user");
var result = new JsonResult(new {status = "success", token});
return result;
}