五月一眨眼就過去,就當湊個數吧。
場景:
一個小小的專案,需要一個後臺,就展示幾個列表,連使用者表、角色表等都不需要設計。
之前有寫過identityserver4和jwt4的demo
(exercisebook/IdentityServer4&Serilog at main · liuzhixin405/exercisebook · GitHub
exercisebook/授權/授權一/JwtToken at main · liuzhixin405/exercisebook · GitHub),
但是這樣一個專案中上這些肯定是大材小用。
微軟提供的還有一個就是cookie,既然夠簡單,那麼什麼也不用設計,儘量做到最簡單,而且後期還可以通過表設計來完善這個的後臺登入模組。
首先我們要實現的就是介面程式碼的授權:
[Authorize] [ApiController] [Route("[controller]")] public class WeatherForecastController : ControllerBase { private static readonly string[] Summaries = new[] { "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching" }; private readonly ILogger<WeatherForecastController> _logger; public WeatherForecastController(ILogger<WeatherForecastController> logger) { _logger = logger; } [Authorize(Roles = "Admin")] // 要求"Admin"角色的授權 [HttpGet(Name = "GetWeatherForecast")] public IEnumerable<WeatherForecast> Get() { return Enumerable.Range(1, 5).Select(index => new WeatherForecast { Date = DateOnly.FromDateTime(DateTime.Now.AddDays(index)), TemperatureC = Random.Shared.Next(-20, 55), Summary = Summaries[Random.Shared.Next(Summaries.Length)] }) .ToArray(); } }
上面的特性使得WeatherForecastController介面需要許可權才能存取,而GetWeatherForecast介面需要Admin角色就可以存取。
下面就通過program來設定及安全中心和授權策略:
using Microsoft.AspNetCore.Authentication.Cookies; namespace auth_cookie { /// <summary> /// 一個簡單的Cookie身份驗證和授權範例 /// </summary> public class Program { public static void Main(string[] args) { var builder = WebApplication.CreateBuilder(args); // Add services to the container. builder.Services.AddControllers(); // 設定Cookie身份驗證 builder.Services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme) .AddCookie(options => { options.Cookie.Name = "YourAuthCookie"; // 設定Cookie的名稱 options.LoginPath = "/api/Auth/Login"; // 設定登入路徑 }); // 設定授權服務 builder.Services.AddAuthorization(options => { options.AddPolicy("RequireAdminRole", policy => policy.RequireRole("Admin")); }); // Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle builder.Services.AddEndpointsApiExplorer(); builder.Services.AddSwaggerGen(); var app = builder.Build(); // Configure the HTTP request pipeline. if (app.Environment.IsDevelopment()) { app.UseSwagger(); app.UseSwaggerUI(); } app.UseHttpsRedirection(); app.UseAuthentication(); // 啟用身份驗證 app.UseAuthorization(); // 啟用授權 app.MapControllers(); app.Run(); } } }
上面的程式碼夠簡單的吧,核心程式碼也就這幾行。指定預設的scheme為cookie,寫好註釋。指定策略RequireAdminRole,要求角色Admin,都可以很靈活的多設定,通過資料庫,組態檔等。
// 設定Cookie身份驗證 builder.Services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme) .AddCookie(options => { options.Cookie.Name = "YourAuthCookie"; // 設定Cookie的名稱 options.LoginPath = "/api/Auth/Login"; // 設定登入路徑 }); // 設定授權服務 builder.Services.AddAuthorization(options => { options.AddPolicy("RequireAdminRole", policy => policy.RequireRole("Admin")); });
這樣不算晚,還需要一個登入和登出的授權的介面,而且介面路徑寫好了,/api/Auth/Login
using Microsoft.AspNetCore.Authentication.Cookies; using Microsoft.AspNetCore.Authentication; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; using System.Security.Claims; namespace auth_cookie.Controllers { [Route("api/[controller]")] [ApiController] public class AuthController : ControllerBase { //[HttpPost("login")] [HttpGet("login")] //方便測試 public async Task<IActionResult> Login(string username, string password) { // 執行驗證使用者名稱和密碼的邏輯 //這裡可以和存到資料庫的使用者和密碼進行比對 if(username != "admin" && password != "123456") { return BadRequest("Invalid username or password"); } // 如果驗證成功,建立身份驗證Cookie var claims = new List<Claim> { new Claim(ClaimTypes.Name, username), new Claim(ClaimTypes.Role, "Admin") // 新增使用者角色 }; var claimsIdentity = new ClaimsIdentity( claims, CookieAuthenticationDefaults.AuthenticationScheme); await HttpContext.SignInAsync( CookieAuthenticationDefaults.AuthenticationScheme, new ClaimsPrincipal(claimsIdentity), new AuthenticationProperties()); return Ok("Login successful"); } //[HttpPost("logout")] [HttpGet("logout")] public async Task<IActionResult> Logout() { await HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme); return Ok("Logout successful"); } } }
上面的核心程式碼根據我們設定的做的設定,一一對應,要不然就無權存取WeatherForecastController了:
var claims = new List<Claim> { new Claim(ClaimTypes.Name, username), new Claim(ClaimTypes.Role, "Admin") // 新增使用者角色 }; var claimsIdentity = new ClaimsIdentity( claims, CookieAuthenticationDefaults.AuthenticationScheme);
下面看看效果,存取 :https://localhost:7066/WeatherForecast,會自動跳轉到https://localhost:7066/api/Auth/Login?ReturnUrl=%2FWeatherForecast
我們指定一下使用者名稱和密碼 https://localhost:7066/api/Auth/Login?username=admin&password=123456ReturnUrl=%2FWeatherForecast
再來存取 https://localhost:7066/WeatherForecast
退出登入,https://localhost:7066/api/auth/logout
再來存取
https://localhost:7066/WeatherForecast
配合前端的後臺管理,一個很簡單的後臺登陸就這樣ok了。
原始碼:
exercisebook/授權/授權三/auth_cookie at main · liuzhixin405/exercisebook · GitHub