NetCore JWT token
Posted 云霄宇霁
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了NetCore JWT token相关的知识,希望对你有一定的参考价值。
在netcore中jwt使用场景很多,网上有很多的资料,这里不再累述,之后有机会会单独介绍,今天主要以实战为主。
1、create jwt token
public interface IJwtTokenService string GetJwtToken(); public class JwtTokenService : IJwtTokenService private readonly IConfiguration _config; public JwtTokenService(IConfiguration config) this._config = config; public string GetJwtToken() var claims = new List<Claim>() new Claim(JwtRegisteredClaimNames.Sub,"jwtsubvalue"), new Claim(JwtRegisteredClaimNames.Name,"jwtnamevalue"), new Claim("Scope","API"), new Claim("Role","Admin") ; var securityKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_config["JwtToken:SecretKey"])); var credentials = new SigningCredentials(securityKey,SecurityAlgorithms.HmacSha256); var issuer = _config["JwtToken:Issuer"]; var audience = _config["JwtToken:Audience"]; var expires = DateTime.Now.AddMinutes(Convert.ToDouble(_config["JwtToken:ExpiredMinutes"])); var jwtToken = new JwtSecurityToken(issuer, audience, claims: claims, notBefore: DateTime.Now, expires: expires, signingCredentials: credentials); return new JwtSecurityTokenHandler().WriteToken(jwtToken);
2、configuration中所需配置信息
"JwtToken": "SecretKey": "12345678901234567890123456789012", "Issuer": "https://localhost:5000", "Audience": "https://localhost:5000", "ExpiredMinutes": 10
3、在Program中配置authentication
var configuration = builder.Configuration; builder.Services.AddAuthentication(options => options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme; options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme; ) .AddJwtBearer(JwtBearerDefaults.AuthenticationScheme, options => options.TokenValidationParameters = new TokenValidationParameters ValidateIssuer = true, ValidateAudience = true, ValidateLifetime = true, ValidateIssuerSigningKey = true, ValidIssuer = configuration["JwtToken:Issuer"], ValidAudience = configuration["JwtToken:Audience"], IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(configuration["JwtToken:SecretKey"])) ; options.Events = new JwtBearerEvents OnTokenValidated = context => var token = context.SecurityToken as JwtSecurityToken; var identity = context.Principal?.Identity as ClaimsIdentity; if (!string.IsNullOrEmpty(token?.Issuer)) context.Success(); else context.Fail($"Token invalid"); return Task.CompletedTask; , OnAuthenticationFailed = context => context.Fail(context.Exception); return Task.CompletedTask; , OnForbidden = context => context.Fail("403 forbidden"); return Task.CompletedTask; , OnChallenge = context => var error = context.Error; return Task.CompletedTask; , OnMessageReceived = context => var token = context.Token; return Task.CompletedTask; ; //Configure authentication scheme forwarding to another scheme options.ForwardDefaultSelector = context => if (context.Request.Headers.TryGetValue("x-api-type", out Microsoft.Extensions.Primitives.StringValues uiTokenType)) return "CustomScheme"; return JwtBearerDefaults.AuthenticationScheme; ; ).AddJwtBearer("CustomScheme", options => options.Authority = configuration["JwtToken:Issuer"]; options.TokenValidationParameters = new TokenValidationParameters ValidateIssuer = true, ValidIssuer = configuration["JwtToken:Issuer"] ; options.Events = new JwtBearerEvents OnTokenValidated = context => context.Success(); return Task.CompletedTask; ; );
4、在请求管道中应用authentication
app.UseAuthentication();
5、添加测试controller,指定[Authorize] atrribute
[Authorize] [HttpGet("all")] public IActionResult Get([FromServices] IConfiguration configuration) return Ok( new ID = 1, Name = "consul service", version = 1.0, serviceIP = configuration["ip"], servicePort = configuration["port"] );
通过swagger测试返回401
6、swagger中authorize之后返回[Authorize] api controller,返回200
下面介绍下如何在swagger中支持authorize及api分组
#region Swagger builder.Services.AddEndpointsApiExplorer(); builder.Services.AddSwaggerGen(c => //c.IgnoreObsoleteActions(); //c.TagActionsBy(api => // // if (api.GroupName != null) // return new[] api.GroupName ; // var controllerActionDescriptor = api.ActionDescriptor as ControllerActionDescriptor; // if (controllerActionDescriptor != null) // return new[] controllerActionDescriptor.ControllerName ; // throw new InvalidOperationException("Unable to determine tag for endpoint."); //); //c.DocInclusionPredicate((name, api) => api.GroupName == "demo1"); c.SwaggerDoc("demo1", new OpenApiInfo Title = "demo1", Description = "this is demo1 v1", Version = "demo1v1" ); c.SwaggerDoc("demo2", new OpenApiInfo Title = "demo2", Description = "this is demo2 v1", Version = "demo2v1" ); c.AddSecurityDefinition("bearerauth", new OpenApiSecurityScheme Name = "Authorization", Type = SecuritySchemeType.Http, Scheme = "Bearer", BearerFormat = "Bearer", In = ParameterLocation.Header, Description = "JWT Authorization header using the Bearer scheme." ); c.AddSecurityRequirement(new OpenApiSecurityRequirement new OpenApiSecurityScheme //Notes: this is for swagger authentication //Type= SecuritySchemeType.Http, //In= ParameterLocation.Header, Reference=new OpenApiReference Type = ReferenceType.SecurityScheme, Id = "bearerauth" , new string[] ); ); #endregion
app.UseSwagger(); app.UseSwaggerUI(c => c.SwaggerEndpoint($"/swagger/demo1/swagger.json", "demo1"); c.SwaggerEndpoint($"/swagger/demo2/swagger.json", "demo2"); );
接下来介绍Authorization Policy及custom policy
builder.Services.AddAuthorization(options => var defaultPolicy = new AuthorizationPolicyBuilder(); defaultPolicy.AddAuthenticationSchemes(JwtBearerDefaults.AuthenticationScheme); defaultPolicy.RequireAuthenticatedUser(); options.DefaultPolicy = defaultPolicy.Build(); options.AddPolicy("CustomScopePolicy", policy => policy.RequireAuthenticatedUser(); policy.RequireClaim("Scope", "API"); ); options.AddPolicy("CustomRolePolicy", policy => policy.RequireAuthenticatedUser(); policy.RequireClaim("Role", "Admin"); ); options.AddPolicy("RoleScopePolicy", policy => policy.RequireAuthenticatedUser(); policy.AddRequirements(new CustomRequirement("admin")); ); ); builder.Services.AddTransient<IJwtTokenService, JwtTokenService>(); builder.Services.AddSingleton<IAuthorizationHandler, CustomRoleBaseAuthorizationHandler>(); builder.Services.AddSingleton<IAuthorizationHandler, CustomScopeBaseAuthorizationHandler>();
app.UseAuthorization();
public class CustomRoleBaseAuthorizationHandler : AuthorizationHandler<CustomRequirement> protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, CustomRequirement requirement) var principal = context.User; var roleClaim = principal.Claims.FirstOrDefault(c => c.Type.Equals("Role", StringComparison.OrdinalIgnoreCase)); if (roleClaim?.Value.Equals(requirement.Role, StringComparison.OrdinalIgnoreCase) ?? false) context.Succeed(requirement); return Task.CompletedTask; public class CustomScopeBaseAuthorizationHandler : AuthorizationHandler<CustomRequirement> protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, CustomRequirement requirement) var principal = context.User; var claim = principal.Claims.FirstOrDefault(c => c.Type.Equals("Scope", StringComparison.OrdinalIgnoreCase)); if (claim?.Value.Equals("API", StringComparison.OrdinalIgnoreCase) ?? false) context.Succeed(requirement); return Task.CompletedTask;
public class CustomRequirement : IAuthorizationRequirement public string Role get; set; public CustomRequirement(string role) Role = role;
添加测试controller
[HttpGet("v1"), Authorize(Policy = "RoleScopePolicy")] public IActionResult Index() return new JsonResult(new List<string> "group1", "group2" ); [HttpGet("v2"),Authorize(Policy = "CustomRolePolicy")] [ApiExplorerSettings(IgnoreApi = false)] public IActionResult IndexV2() return new JsonResult(new List<string> "group3", "group4" );
测试结果
OK 搞定!
以上是关于NetCore JWT token的主要内容,如果未能解决你的问题,请参考以下文章
从零开始搭建前后端分离的NetCore2.2(EF Core CodeFirst+Autofac)+Vue的项目框架之七使用JWT生成Token(个人见解)