-- 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
常见问题
快速入门
无