身份验证是这样一个过程:由用户提供凭据,然后将其与存储在操作系统、数据库、应用或资源中的凭据进行比较。 在授权过程中,如果凭据匹配,则用户身份验证成功,可执行已向其授权的操作。 授权指判断允许用户执行的操作的过程。也可以将身份验证理解为进入空间(例如服务器、数据库、应用或资源)的一种方式,而授权是用户可以对该空间(服务器、数据库或应用)内的哪些对象执行哪些操作。
微软官方文档
asp.net core支持 多 种授 权 ,本篇 重点说明 JW T的基于角色 授权方式。
基于JWT角色身份验证和授权,思路是在登录时分发加密的Token,在访问资源时带有这个Token,服务端要验证这个Token是不是自己分发的,如果是,再验证访问范围是否正确,本篇的范围就是那些资源是那种角色访问,得到Token的用户当前是那种角色,也就是角色和资源的匹配。
用asp.net core实现步骤:
1、appsettings.json中配置JWT参
2、添加身份认证和授权服务和中间件
3、定义生成Token的方法和验证Toekn参数的方法
4、登录时验证身份并分发Toekn
using Microsoft.AspNetCore.Authentication.JwtBearer; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Identity; using Microsoft.IdentityModel.Tokens; using System.IdentityModel.Tokens.Jwt; using System.Security.Claims; using System.Text; var builder = WebApplication.CreateBuilder(); //获取JWT参数,并注入到服务容器 var jwtConfig = new JWTConfig(); builder.Configuration.GetSection("JWTConfig").Bind(jwtConfig); builder.Services.AddSingleton(jwtConfig); //添加JJWT方式的身份认证和授权, builder.Services .AddAuthorization() .AddAuthentication(options => { options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme; options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme; }) .AddJwtBearer(JwtBearerDefaults.AuthenticationScheme, opt => { opt.RequireHttpsMetadata = false; opt.TokenValidationParameters = JwtToken.CreateTokenValidationParameters(jwtConfig); }); var app = builder.Build(); //使用身份认证和授权的中间件 app.UseAuthentication(); app.UseAuthorization(); app.MapGet("/hellosystem", (ILogger<Program> logger, HttpContext context) => { var message = $"hello,system,{context.User?.Identity?.Name}"; logger.LogInformation(message); return message; }).RequireAuthorization(new RoleData { Roles = "system" }); app.MapGet("/helloadmin", (ILogger<Program> logger, HttpContext context) => { var message = $"hello,admin,{context.User?.Identity?.Name}"; logger.LogInformation(message); return message; }).RequireAuthorization(new RoleData { Roles = "admin" }); app.MapGet("/helloall", (ILogger<Program> logger, HttpContext context) => { var message = $"hello,all roles,{context.User?.Identity?.Name}"; logger.LogInformation(message); return message; }).RequireAuthorization(new RoleData { Roles = "admin,system" }); //登录成功,并分发Token app.MapPost("/login", [AllowAnonymous] (ILogger<Program> logger, LoginModel login, JWTConfig jwtConfig) => { logger.LogInformation("login"); if (login.UserName == "gsw" && login.Password == "111111") { var now = DateTime.UtcNow; var claims = new Claim[] { new Claim(ClaimTypes.Role, "admin"), new Claim(ClaimTypes.Name, "桂素伟"), new Claim(ClaimTypes.Sid, login.UserName), new Claim(ClaimTypes.Expiration, now.AddSeconds(jwtConfig.Expires).ToString()) }; var token = JwtToken.BuildJwtToken(claims, jwtConfig); return token; } else { return "username or password is error"; } }); app.Run(); //登录实体 public class LoginModel { public string? UserName { get; set; } public string? Password { get; set; } } //JWT配置 public class JWTConfig { public string? Secret { get; set; } public string? Issuer { get; set; } public string? Audience { get; set; } public int Expires { get; set; } } //JWT操作类型 public class JwtToken { //获取Token public static dynamic BuildJwtToken(Claim[] claims, JWTConfig jwtConfig) { var now = DateTime.UtcNow; var jwt = new JwtSecurityToken( issuer: jwtConfig.Issuer, audience: jwtConfig.Audience, claims: claims, notBefore: now, expires: now.AddSeconds(jwtConfig.Expires), signingCredentials: GetSigningCredentials(jwtConfig) ); var encodedJwt = new JwtSecurityTokenHandler().WriteToken(jwt); var response = new { Status = true, AccessToken = encodedJwt, ExpiresIn = now.AddSeconds(jwtConfig.Expires), TokenType = "Bearer" }; return response; } static SigningCredentials GetSigningCredentials(JWTConfig jwtConfig) { var keyByteArray = Encoding.ASCII.GetBytes(jwtConfig?.Secret!); var signingKey = new SymmetricSecurityKey(keyByteArray); return new SigningCredentials(signingKey, SecurityAlgorithms.HmacSha256); } //验证Token的参数 public static TokenValidationParameters CreateTokenValidationParameters(JWTConfig jwtConfig) { var keyByteArray = Encoding.ASCII.GetBytes(jwtConfig?.Secret!); var signingKey = new SymmetricSecurityKey(keyByteArray); return new TokenValidationParameters { ValidateIssuerSigningKey = true, IssuerSigningKey = signingKey, ValidateIssuer = true, ValidIssuer = jwtConfig?.Issuer, ValidateAudience = true, ValidAudience = jwtConfig?.Audience, ClockSkew = TimeSpan.Zero, RequireExpirationTime = true, }; } } //mini api添加验证授权的参数类型 public class RoleData : IAuthorizeData { public string? Policy { get; set; } public string? Roles { get; set; } public string? AuthenticationSchemes { get; set; } }
验证结果:
1、没有登录,返回401
2、登录,取token
3、正确访问
4、没有授权访问,返回403