在 Blazor 上做登入功能,我原以為會比傳統的 ASP.NET 專案簡單,但事實上沒有,先說結論,還是要寫 controller。

首先,我把邏輯抽到 service,所以需要透過 DI 取得 IHttpContextAccessor 物件:

private IHttpContextAccessor _httpContextAccessor;

public UserAppService(IHttpContextAccessor httpContextAccessor) 
{
    _httpContextAccessor = httpContextAccessor;
}

接下來登入的程式碼就好寫了,網路上很多範例:

public async Task<bool> Login(string username, string password)
{
    if (UserData.UserName == username && UserData.UserPassword == password)
    {
        ClaimsIdentity claimsIdentity = new ClaimsIdentity(new List<Claim>
        {
            new Claim(ClaimTypes.NameIdentifier, username)
        }, "auth");
        ClaimsPrincipal claims = new ClaimsPrincipal(claimsIdentity);
        await _httpContextAccessor.HttpContext.SignInAsync(claims);
        return true;
    }
    return false;
}

public async Task Logout()
{
    await _httpContextAccessor.HttpContext.SignOutAsync();
}

public bool CheckLoginState()
{
    if (_httpContextAccessor.HttpContext.User.Identity.IsAuthenticated)
    {
        return true;
    }
    return false; 
}

再來是登入的畫面,雖然是 blazor 頁面,但加入的還是傳統的 Form:

@page "/Login"
@using AIPicturesAlbumWebAP.Data;
@inject IUserAppService userAppService
<h3>登入</h3>

<form method="post" action="Auth">
    <input type="text" name="UserName" />
    <input type="password" name="Password" />
    <input type="submit" value="登入" />
</form>

@code {

}

最後是 controller,這部份也是沒什麼特別的,就是拿到參數後由 service 執行登入:

[Route("/[controller]")]
[ApiController]
public class AuthController : ControllerBase
{
    private IUserAppService _userAppService;
    public AuthController(IUserAppService userAppService) 
    {
        _userAppService = userAppService;
    }

    [HttpPost]
    public async Task<IActionResult> Login([FromForm] LoginModel loginModel) 
    {
        var isLogin = await _userAppService.Login(loginModel.UserName, loginModel.Password);
        if (isLogin)
        {
            return Redirect("/UploadPic");
        }

        return Redirect("/Login");
    }
}

最後別漏掉在 Program.cs 上的設定:

builder.Services.AddAuthentication("Cookies").AddCookie();
builder.Services.AddHttpContextAccessor();

有興趣的可以到 GitHub 頁面看原始碼:

Source Code

參考資料