Preview5對策略驗證的方式沒有改變,只不過內置了Token的生成,和《.NET6之MiniAPI(十):基于策略的身份驗證和授權》的驗證方式基本相同,都是生成和驗證使用的驗證參數要一致,用繼承AuthorizationHandler的子類來作每次請求的驗證。
在具體的路由上,用RequireAuthorization("Permission")來配置策略名稱,以達到請求轉向驗證。
不多說了,看代碼實現,可以《.NET6之MiniAPI(十):基于策略的身份驗證和授權》作個比較。
using?Microsoft.AspNetCore.Authorization;
using Microsoft.IdentityModel.Tokens;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Text;var builder = WebApplication.CreateBuilder(args);#region?添加策略驗證參數
builder.Authentication.AddJwtBearer(opt =>
{????opt.TokenValidationParameters = new TokenValidationParameters{ValidateIssuerSigningKey = true,IssuerSigningKey = new SymmetricSecurityKey(Encoding.ASCII.GetBytes("1234567890abcdefg")),ValidateIssuer = true,ValidIssuer = "http://localhost:5274",ValidateAudience = true,ValidAudience = "http://localhost:5274",ClockSkew = TimeSpan.Zero,RequireExpirationTime = true,}; ;
});//添加策略名和注與策略驗證服務
builder.Services.AddAuthorization(options =>{//添加策略名稱options.AddPolicy("Permission", policyBuilder => policyBuilder.AddRequirements(new PermissionRequirement()));}).AddSingleton(new List<Permission> { new Permission { RoleName = "admin", Url = "/Policy", Method = "get" } }).AddSingleton<IAuthorizationHandler, PermissionHandler>();var app = builder.Build();
//登錄,生成token
app.MapGet("/login",?()?=>
{//用JWTSecurityTokenHandler生成tokenreturn new JwtSecurityTokenHandler().WriteToken(new JwtSecurityToken(issuer: "http://localhost:5274",audience: "http://localhost:5274",claims: new Claim[] {new Claim(ClaimTypes.Role, "admin"),new Claim(ClaimTypes.Name, "桂素偉")},notBefore: DateTime.UtcNow,expires: DateTime.UtcNow.AddSeconds(500000),signingCredentials: new SigningCredentials(new SymmetricSecurityKey(Encoding.ASCII.GetBytes("1234567890abcdefg")),SecurityAlgorithms.HmacSha256)));
});
app.MapGet("/policy", (ClaimsPrincipal user) => $"Hello 用戶:{user.Identity?.Name}, 角色:{user.Claims?.Where(s => s.Type == ClaimTypes.Role).First().Value}. This is a policy!").RequireAuthorization("Permission");
app.Run();#region?策略驗證功能
public class PermissionRequirement : IAuthorizationRequirement
{
}
//權限的實體集合
public class Permission
{public string? RoleName { get; set; }public string? Url { get; set; }public string? Method { get; set; }
}
//權限驗證類
public class PermissionHandler : AuthorizationHandler<PermissionRequirement>
{private readonly List<Permission> _userPermissions;public PermissionHandler(List<Permission> permissions){_userPermissions = permissions;}protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, PermissionRequirement requirement){if (context.Resource is DefaultHttpContext){var httpContext = context.Resource as DefaultHttpContext;var questPath = httpContext?.Request?.Path;var method = httpContext?.Request?.Method;var isAuthenticated = context?.User?.Identity?.IsAuthenticated;if (isAuthenticated.HasValue && isAuthenticated.Value){var role = context?.User?.Claims?.SingleOrDefault(s => s.Type == ClaimTypes.Role)?.Value;if (_userPermissions.Where(w => w.RoleName == role && w.Method?.ToUpper() == method?.ToUpper() && w.Url?.ToLower() == questPath).Count() > 0){context?.Succeed(requirement);}else{context?.Fail();}}}return Task.CompletedTask;}
}
#endregion