ASP.NET Core MVC 自訂登入並使用 Cookie 驗證

在 ASP.NET Core 中使用預設 Cookie 登入驗證方案,什麼事情都會幫你處理完,包含帳號密碼驗證和後面的 cookie。

在 Login.cshtml.cs 中我們可以看到下面這段自動建立的程式碼:
    
private readonly SignInManager<User> _signInManager;

// 省略部分

public async Task<IActionResult> OnPostAsync(string returnUrl = null)
{
    returnUrl ??= Url.Content("~/");

    ExternalLogins = (await _signInManager.GetExternalAuthenticationSchemesAsync()).ToList();

    if (ModelState.IsValid)
    {
        var result = await _signInManager.PasswordSignInAsync(Input.Email, Input.Password, Input.RememberMe, lockoutOnFailure: false);
        if (result.Succeeded)
        {
            _logger.LogInformation("User logged in.");
            return LocalRedirect(returnUrl);
        }
        if (result.RequiresTwoFactor)
        {
            return RedirectToPage("./LoginWith2fa", new { ReturnUrl = returnUrl, RememberMe = Input.RememberMe });
        }
        if (result.IsLockedOut)
        {
            _logger.LogWarning("User account locked out.");
            return RedirectToPage("./Lockout");
        }
        else
        {
            ModelState.AddModelError(string.Empty, "Invalid login attempt.");
            return Page();
        }
    }

    return Page();
}
    

疑?那 cookie 怎麼做的?該不會在 _signInManager.PasswordSignInAsync 這個方法裡面就自動做好了吧?那假設我想要自己實作其他登入且不會知道使用者的密碼,那該怎麼辦?我就要自己處理 cookie 了嗎?

經過一翻研究,發現有個很簡單的方式,就是使用 SignInAsync 即可。只要找到使用者,就可以直接使用框架做好的方法幫我們處理登入的 cookie
    
public async Task<IActionResult> OnPostAsync(string returnUrl = null)
{
    returnUrl ??= Url.Content("~/");
    
    User? user = _context.Users.FirstOrDefault(x => x.UserName == Input.UserName);
    if(user == null)
    {
        ModelState.AddModelError(string.Empty, "找不到使用者");
        return Page();
    }
    
    await _signInManager.SignInAsync(user, true);
    return LocalRedirect(returnUrl);
}
    

註1:這裡的 User 是繼承 IdentityUser 的 class: User
註2:這裡的 _context 是繼承 IdentityDbContext 的 DbContext

參考資料:
Microsoft.Learn - SignInManager<TUser>.SignInAsync Method

留言