在 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。