在 ASP.NET Core MVC 應用中實現使用 JWT 的登入功能並將 JWT token 保存到 Session 中,涉及以下步驟: 創建登入頁面:用戶輸入他們的憑證(如用戶名和密碼)。 發送登入請求:從 MVC 應用發送一個請求到 API 來獲取 JWT。 存儲 JWT:將 JWT 存儲在 Session 中。 設置授權標頭:在後續請求中使用 JWT 進行身份驗證。 步驟 1:創建登入頁面 首先,在你的 MVC 應用中創建一個簡單的登入頁面,讓用戶輸入用戶名和密碼。 html <!-- Views/Account/Login.cshtml --> @{ ViewData["Title"] = "Login"; } <h2>@ViewData["Title"]</h2> <form asp-action="Login" method="post"> <div> <label asp-for="Username"></label> <input asp-for="Username" /> </div> <div> <label asp-for="Password"></label> <input asp-for="Password" type="password" /> </div> <button type="submit">Login</button> </form> 步驟 2:創建登入模型 在 MVC 應用中創建一個模型來綁定登入頁面的輸入。 csharp // Models/LoginViewModel.cs using System.ComponentModel.DataAnnotations; public class LoginViewModel { [Required] public string Username { get; set; } [Required] public string Password { get; set; } } 步驟 3:創建控制器來處理登入請求 創建一個控制器來處理登入邏輯,包括發送請求到 API 並獲取 JWT,然後將 JWT 存儲在 Session 中。 csharp // Controllers/AccountController.cs using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; using System.Net.Http; using System.Net.Http.Headers; using System.Text; using System.Text.Json; using System.Threading.Tasks; using YourNamespace.Models; public class AccountController : Controller { private readonly IHttpClientFactory _httpClientFactory; public AccountController(IHttpClientFactory httpClientFactory) { _httpClientFactory = httpClientFactory; } [HttpGet] public IActionResult Login() { return View(); } [HttpPost] public async Task<IActionResult> Login(LoginViewModel model) { if (!ModelState.IsValid) { return View(model); } var client = _httpClientFactory.CreateClient(); var loginUrl = "https://yourapi.com/api/auth/login"; var loginData = new { Username = model.Username, Password = model.Password }; var content = new StringContent(JsonSerializer.Serialize(loginData), Encoding.UTF8, "application/json"); var response = await client.PostAsync(loginUrl, content); if (response.IsSuccessStatusCode) { var responseString = await response.Content.ReadAsStringAsync(); var jwt = JsonSerializer.Deserialize<JwtResponse>(responseString); // 存儲 JWT 到 Session HttpContext.Session.SetString("JWT", jwt.Token); return RedirectToAction("Index", "Home"); } ModelState.AddModelError(string.Empty, "Invalid login attempt."); return View(model); } } public class JwtResponse { public string Token { get; set; } } 步驟 4:配置 Session 在 Startup.cs 中配置 Session。 csharp public void ConfigureServices(IServiceCollection services) { services.AddHttpClient(); services.AddControllersWithViews(); services.AddSession(options => { options.IdleTimeout = TimeSpan.FromMinutes(30); // 可以根據需求調整 options.Cookie.HttpOnly = true; options.Cookie.IsEssential = true; }); } public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } else { app.UseExceptionHandler("/Home/Error"); app.UseHsts(); } app.UseHttpsRedirection(); app.UseStaticFiles(); app.UseRouting(); app.UseSession(); // 必須在 UseRouting 和 UseAuthentication 之間 app.UseAuthentication(); app.UseAuthorization(); app.UseEndpoints(endpoints => { endpoints.MapControllerRoute( name: "default", pattern: "{controller=Home}/{action=Index}/{id?}"); }); } 步驟 5:設置授權標頭 在每次發送 HTTP 請求時,從 Session 中獲取 JWT 並設置授權標頭。 csharp public class AuthorizedHttpClientHandler : DelegatingHandler { private readonly IHttpContextAccessor _httpContextAccessor; public AuthorizedHttpClientHandler(IHttpContextAccessor httpContextAccessor) { _httpContextAccessor = httpContextAccessor; } protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) { var token = _httpContextAccessor.HttpContext.Session.GetString("JWT"); if (!string.IsNullOrEmpty(token)) { request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", token); } return await base.SendAsync(request, cancellationToken); } } public void ConfigureServices(IServiceCollection services) { services.AddHttpClient("AuthorizedClient") .AddHttpMessageHandler<AuthorizedHttpClientHandler>(); services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>(); services.AddTransient<AuthorizedHttpClientHandler>(); services.AddControllersWithViews(); services.AddSession(options => { options.IdleTimeout = TimeSpan.FromMinutes(30); options.Cookie.HttpOnly = true; options.Cookie.IsEssential = true; }); } 使用 AuthorizedHttpClient 發送請求 在需要授權的請求中使用 AuthorizedHttpClient。 csharp public class SomeController : Controller { private readonly IHttpClientFactory _httpClientFactory; public SomeController(IHttpClientFactory httpClientFactory) { _httpClientFactory = httpClientFactory; } public async Task<IActionResult> SomeAction() { var client = _httpClientFactory.CreateClient("AuthorizedClient"); var response = await client.GetAsync("https://yourapi.com/api/protectedresource"); if (response.IsSuccessStatusCode) { var data = await response.Content.ReadAsStringAsync(); // 處理數據 } else { // 處理錯誤 } return View(); } } 將這些部分組合起來,你將擁有一個完整的 MVC 應用,允許用戶登入並將 JWT 存儲在 Session 中,從而在後續的請求中使用這個 JWT 進行身份驗證。 這種方式不僅實現了基於 JWT 的身份驗證,還充分利用了 ASP.NET Core 的 Session 管理功能來安全地存儲和使用 JWT。