-- asp.net core 支持多中Authentication,通过header头区分jwttoken,走不不同的TokenValidationParameters
【官网】:https://docs.microsoft.com/en-us/aspnet/core/security/?view=aspnetcore-5.0
应用场景
在asp.net core 的应用中,启用jwttoken后,往往有些场景需要我们启用多种验证方式,比如我们api自身有一种默认身份验证,同时针对合作伙伴也需要一种。 比如有时合作伙伴和我们的api应用有公钥/私钥的配置和校验,这时就需要专门有一种方案识别采用哪一种jwttoken的验证参数。基础资源
本文示例为asp.net core 3.1 (建议>=3.1)
使用须知
具体应用需要结合实际业务场景来决定. 无论采取何种方式,都需要充分测试: 匿名api, 无特殊头的jwttoken验证,有特殊头的jwttoken, 非匿名api的无凭据访问等场景。
配置步骤
[注]关于如何在asp.net core中启用jwttoken验证,请自行百度,这里主要介绍一下多种Authentication的处理.
步骤1: 添加多个Authentication Schema。
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme) .AddJwtBearer(options => { options.TokenValidationParameters = new TokenValidationParameters() { ValidateLifetime = true, ValidateAudience = true, ValidateIssuer = true, ValidIssuer = _appSetting.Default.Issuer, ValidAudience = _appSetting.Default.Audience, ValidateIssuerSigningKey = true, IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_appSetting.Default.SecurityKey)) }; }) .AddJwtBearer(AuthSchema.Partner, options => { options.TokenValidationParameters = new TokenValidationParameters() { ValidateLifetime = true, ValidateAudience = true, ValidateIssuer = true, ValidIssuer = _appSetting.Partner.Issuer, ValidAudience = _appSetting.Partner.Audience, ValidateIssuerSigningKey = true, IssuerSigningKey = new ECDsaSecurityKey(EcdsaUtils.LoadPublicKey(_appSetting.Partner.SecurityKey)) }; });
步骤2: 添加一个自定义的AuthorizationFilter特性。
using Microsoft.AspNetCore.Authentication; using Microsoft.AspNetCore.Authentication.JwtBearer; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.Filters; using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; namespace ConfigLab.Dnc.Tester.Controllers.Share.Commons { public class BaseAthenticationAttr: Attribute, IAuthorizationFilter { public void OnAuthorization(AuthorizationFilterContext context) { string reqAuthSchema = context.HttpContext?.Request?.Headers["AuthSchema"]; var realAuthSchema = AuthSchema.GetAuthSchema(reqAuthSchema); var res = context.HttpContext.AuthenticateAsync(realAuthSchema).Result; if (!res.Succeeded&&!HasAllowAnonymous(context))//身份验证失败 { context.Result = new ObjectResult(res?.Failure?.Message) { StatusCode = 401 }; } }
private bool HasAllowAnonymous(AuthorizationFilterContext context) { var filters = context.Filters; for (var i = 0; i < filters.Count; i++) { if (filters[i] is IAllowAnonymousFilter) { return true; } } // When doing endpoint routing, MVC does not add AllowAnonymousFilters for AllowAnonymousAttributes that // were discovered on controllers and actions. To maintain compat with 2.x, // we‘ll check for the presence of IAllowAnonymous in endpoint metadata. var endpoint = context.HttpContext.GetEndpoint(); if (endpoint?.Metadata?.GetMetadata<IAllowAnonymous>() != null) { return true; } return false; }
}
public static class AuthSchema { public static readonly List<string> ListAuthSchema = new List<string>(); static AuthSchema() { ListAuthSchema.AddRange(new string[] {Partner }); } public static string GetAuthSchema(string authSchema) { if (ListAuthSchema.Contains(authSchema)) return authSchema; return JwtBearerDefaults.AuthenticationScheme; } public const string Partner = "Partner"; } }
步骤3:应用到controller中.
[BaseAthenticationAttr] [Route("api/[controller]")] [ApiController] public class ApiBaseController : ControllerBase { }
---------------------------------------至此,支持多种Authentication的处理已经完成,下面开始介绍调用时的处理---------------------
http请求我们这里先不介绍参数,请求方式等,只关注与jwttoken验证相关的。
1)默认的调用请求Header头示例.
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJodHRwOi8vc2NoZW1hcy54bWxzb2FwLm9yZy93cy8yMDA1LzA1L2lkZW50aXR5L2NsYWltcy9uYW1lIjoiYXV0aC5jb25maWcubmV0LmNuIiwic3ViIjoidXNlcl90ZXN0IiwiaHR0cDovL3NjaGVtYXMueG1sc29hcC5vcmcvd3MvMjAwNS8wNS9pZGVudGl0eS9jbGFpbXMvZGF0ZW9mYmlydGgiOiIxNjAyMDk4MDg4IiwiaHR0cDovL3NjaGVtYXMubWljcm9zb2Z0LmNvbS93cy8yMDA4LzA2L2lkZW50aXR5L2NsYWltcy9leHBpcmF0aW9uIjoiMTYwMjA5ODEwOCIsIm5iZiI6MTYwMjA5ODA4OCwiZXhwIjoxNjAyMDk4MTA4LCJpc3MiOiJhdXRoLmNvbmZpZy5uZXQuY24iLCJhdWQiOiJjb25maWcubmV0LmNuIn0.7PGl0u9M7MQxtA182DVgnMbz42E_3IAbQhBISUtiYCw
2)合作方的调用请求Header头。
AuthSchema:Partner //这里就是指定走哪一个jwttoken验证的
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJodHRwOi8vc2NoZW1hcy54bWxzb2FwLm9yZy93cy8yMDA1LzA1L2lkZW50aXR5L2NsYWltcy9uYW1lIjoiYXV0aC5jb25maWcubmV0LmNuIiwic3ViIjoidXNlcl90ZXN0IiwiaHR0cDovL3NjaGVtYXMueG1sc29hcC5vcmcvd3MvMjAwNS8wNS9pZGVudGl0eS9jbGFpbXMvZGF0ZW9mYmlydGgiOiIxNjAyMDk4MDg4IiwiaHR0cDovL3NjaGVtYXMubWljcm9zb2Z0LmNvbS93cy8yMDA4LzA2L2lkZW50aXR5L2NsYWltcy9leHBpcmF0aW9uIjoiMTYwMjA5ODEwOCIsIm5iZiI6MTYwMjA5ODA4OCwiZXhwIjoxNjAyMDk4MTA4LCJpc3MiOiJhdXRoLmNvbmZpZy5uZXQuY24iLCJhdWQiOiJjb25maWcubmV0LmNuIn0.7PGl0u9M7MQxtA182DVgnMbz42E_3IAbQhBISUtiYCw
常见问题
快速入门
无