当前位置: 首页 > news >正文

【开发技术】Abp.vnext下的JWT处理,添加多种认证处理方式

目录

一、目的

二、解决方案

2.1 什么是认证和授权

2.2 支持标准 JWT Bearer 认证

2.2.1 引用“Microsoft.AspNetCore.Authentication.JwtBearer”

2.2.2 调用 AddAuthentication 和 AddJwtBearer 注册服务

2.2.3 在 appsettings.json 配置密钥、颁发者等参数

2.3 自定义认证

2.4 自定义授权处理

2.4.1需要实现自定义授权处理器

2.4.2 配置授权策略

2.5 配置授权策略

三、文章总结


一、目的

当前开发一个Api服务时,可能存在多种服务调用请求场景,例如:App\Web\小程序、内部项目、第三方对接等请求Api。本文展示基于Abp.vnext应用架构下,使用JWT支持多种场景的认证和授权。
 认证流程:        
多种认证和授权流程:

二、解决方案

2.1 什么是认证和授权

        认证:即身份认证,因为Htpp协议是无状态的,每个Http请求发过来是无法识别身份的。为了进行身份识别,一般需要你提供一个账号和密码进行登录,登录通过则表示你是正常用户,给你颁发一个身份标识。通过这个身份标识去访问其他服务时,会检查你是否有有这身份标识,有则标识为认证用户,运行请求,没有则会拒绝。 举个例子:看演唱会或则坐车,买了票后,需要凭相关票据才可进入会场。
        授权:即授予权限,当你认证通过后需要请求某个页面或则某个服务方法时,会检查分配的唯一标识是否有权限。 举个例子:看演唱会买了看台的票,你想去坐VIP位置,这显然是需要加钱的。

2.2 支持标准 JWT Bearer 认证

使用流程:
  • 显式安装 NuGet 包
  • 调用 AddAuthentication 和 AddJwtBearer 注册服务
  • 在 appsettings.json 配置密钥、颁发者等参数

2.2.1 引用“Microsoft.AspNetCore.Authentication.JwtBearer”

dotnet add package Microsoft.AspNetCore.Authentication.JwtBearer
dotnet add package Microsoft.IdentityModel.Tokens
dotnet add package System.IdentityModel.Tokens.Jwt

2.2.2 调用 AddAuthentication 和 AddJwtBearer 注册服务

基础示例:
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme).AddJwtBearer(options => { /* 参数配置 */ }); 
实际使用:
namespace Demo.HttpApi.Host;public class DemoHttpApiHostModule : AbpModule
{public override void ConfigureServices(ServiceConfigurationContext context){var services = context.Services;var configuration = services.GetConfiguration();// 跨域context.Services.AddCors(options =>{options.AddPolicy("AllowAll", builder =>{builder.AllowAnyOrigin().SetIsOriginAllowedToAllowWildcardSubdomains().AllowAnyHeader().AllowAnyMethod();});});// Configure Jwt AuthenticationConfigureAuthentication(context);}public override void OnApplicationInitialization(ApplicationInitializationContext context){var app = context.GetApplicationBuilder();// 定义在2者之间//app.UseRouting();app.UseAuthentication();//app.UseConfiguredEndpoints();}private void ConfigureAuthentication(ServiceConfigurationContext context){var services = context.Services;var configuration = services.GetConfiguration();string issuer = configuration["Jwt:Issuer"];string audience = configuration["Jwt:Audience"];string expire = configuration["Jwt:ExpireMinutes"];TimeSpan expiration = TimeSpan.FromMinutes(Convert.ToDouble(expire));SecurityKey key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(configuration["Jwt:SecurityKey"]));services.AddAuthentication(s =>{// 2、Authentications.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;s.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;s.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;}).AddJwtBearer(s =>{// 3、Use Jwt bearer s.TokenValidationParameters = new TokenValidationParameters{ValidIssuer = issuer,ValidAudience = audience,IssuerSigningKey = key,ClockSkew = expiration,ValidateLifetime = true};s.Events = new JwtBearerEvents{OnAuthenticationFailed = context =>{// Token expiredif (context.Exception.GetType() == typeof(SecurityTokenExpiredException)){context.Response.Headers.Add("Token-Expired", "true");}return Task.CompletedTask;}};});}
}

2.2.3 在 appsettings.json 配置密钥、颁发者等参数

{"Jwt": {"Issuer": "***.com",//发行人"Audience": "***.com",//接收者"SecurityKey": "*****",//密钥"ExpireMinutes": "60"//过期时间,单位:分钟}
}

2.3 自定义认证

在某些情况下我们需要添加一些内部的自定义认证,用于识别内部系统调用,或则是其他第三方接口,用于执行一些特殊处理逻辑。
增加自定义的Scheme:“InternalAuth”.通过AddScheme添加认证逻辑,以及认证处理器来处理认证逻辑,完成对于调用端身份认证。
 /// <summary>/// jwt设置/// </summary>/// <param name="context"></param>private void ConfigureAuthentication(ServiceConfigurationContext context){var services = context.Services;var configuration = services.GetConfiguration();string issuer = configuration["Jwt:Issuer"];string audience = configuration["Jwt:Audience"];string expire = configuration["Jwt:ExpireMinutes"];TimeSpan expiration = TimeSpan.FromMinutes(Convert.ToDouble(expire));SecurityKey key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(configuration["Jwt:SecurityKey"]));services.AddAuthentication(s =>{// 2、Authentications.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;s.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;s.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;}).AddJwtBearer(s =>{// 3、Use Jwt bearer s.TokenValidationParameters = new TokenValidationParameters{ValidIssuer = issuer,ValidAudience = audience,IssuerSigningKey = key,ClockSkew = expiration,ValidateLifetime = true};s.Events = new JwtBearerEvents{OnAuthenticationFailed = context =>{// Token expiredif (context.Exception.GetType() == typeof(SecurityTokenExpiredException)){context.Response.Headers.Add("Token-Expired", "true");}return Task.CompletedTask;}};})// 添加内部认证方案.AddScheme<InternalAuthOptions, InternalAuthHandler>("InternalAuth",opts => { }); // 可以配置选项如果有需要;}
public class InternalAuthOptions : AuthenticationSchemeOptions
{// 可以添加自定义选项,比如头名称等
}public class InternalAuthHandler : AuthenticationHandler<InternalAuthOptions>
{public InternalAuthHandler(IOptionsMonitor<InternalAuthOptions> options,ILoggerFactory logger,UrlEncoder encoder,ISystemClock clock): base(options, logger, encoder, clock){}protected override Task<AuthenticateResult> HandleAuthenticateAsync(){var authHeader = Request.Headers["X-Internal-Auth-Token"].ToString();// 这里添加你的内部认证逻辑if (string.IsNullOrEmpty(authHeader) || authHeader != "你的内部认证密钥"){return Task.FromResult(AuthenticateResult.Fail("内部认证令牌无效"));}// 创建身份主体var claims = new[] { new Claim(ClaimTypes.Name, "InternalSystem") };var identity = new ClaimsIdentity(claims, Scheme.Name);var principal = new ClaimsPrincipal(identity);var ticket = new AuthenticationTicket(principal, Scheme.Name);return Task.FromResult(AuthenticateResult.Success(ticket));}
}

2.4 自定义授权处理

2.4.1需要实现自定义授权处理器

public class InternalRequirement : IAuthorizationRequirement
{
}public class InternalHandler : AuthorizationHandler<InternalRequirement>
{protected override Task HandleRequirementAsync(AuthorizationHandlerContext context,InternalRequirement requirement){// 如果通过JWT或者内部认证任一成功,则授权通过if (context.User.Identity.IsAuthenticated){context.Succeed(requirement);}return Task.CompletedTask;}
}

2.4.2 配置授权策略

   /// <summary>/// jwt授权设置/// </summary>/// <param name="context"></param>private void ConfigureAuthentication(ServiceConfigurationContext context){var services = context.Services;var configuration = services.GetConfiguration();string issuer = configuration["Jwt:Issuer"];string audience = configuration["Jwt:Audience"];string expire = configuration["Jwt:ExpireMinutes"];TimeSpan expiration = TimeSpan.FromMinutes(Convert.ToDouble(expire));SecurityKey key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(configuration["Jwt:SecurityKey"]));services.AddAuthorization(options =>{// 1、Definition authorization policyoptions.AddPolicy("Permission", policy => policy.Requirements.Add(new InternalRequirement()));}).AddAuthentication(s =>{// 2、Authentications.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;s.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;s.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;}).AddJwtBearer(s =>{// 3、Use Jwt bearer s.TokenValidationParameters = new TokenValidationParameters{ValidIssuer = issuer,ValidAudience = audience,IssuerSigningKey = key,ClockSkew = expiration,ValidateLifetime = true};s.Events = new JwtBearerEvents{OnAuthenticationFailed = context =>{// Token expiredif (context.Exception.GetType() == typeof(SecurityTokenExpiredException)){context.Response.Headers.Add("Token-Expired", "true");}return Task.CompletedTask;}};})// 添加内部认证方案.AddScheme<InternalAuthOptions, InternalAuthHandler>("InternalAuth",opts => { }); // 可以配置选项如果有需要;//注入授权处理器services.AddSingleton<IAuthorizationHandler, InternalHandler>();}public override void OnApplicationInitialization(ApplicationInitializationContext context){var app = context.GetApplicationBuilder();// 定义在2者之间//app.UseRouting();app.UseAuthentication();app.UseAuthorization();//app.UseConfiguredEndpoints();}

2.5 配置授权策略

在控制器或应用服务上使用授权特性:

[Authorize(Policy = "InternalAuth")]
public class MyAppService : ApplicationService
{// ...
}
针对特定方法:
[Authorize(Policy = "InternalAuth")]
public async Task<MyDto> GetDataAsync()
{// ...
}
若有多个Scheme和Policy :
 [Authorize(AuthenticationSchemes = $"{JwtBearerDefaults.AuthenticationScheme},InternalAuth", Policy = "Permission")]public class MyAppService : ApplicationService
{// ...
}

三、文章总结

在.netCore中认证和授权都是通过中间件的方式进行处理,弄清楚实现原理,在今后的开发中会更易于针对不同场景进行扩展和应用。文章内部当前未加入对于Jwt Token生成部分,这块网络挺多的就不重复编写了。
把之所学以文载之,欢迎大家多多交流~

相关文章:

  • ES Serverless 8.17王牌发布:向量检索「火力全开」,智能扩缩「秒级响应」!
  • 完整的加密解密aes
  • C#中清空DataGridView的方法
  • rk3568 , mipi 屏幕调试(3588s 可以显示,但是3568 不能显示)
  • 【堆垛策略】设计方法
  • NFT模式:数字资产确权与链游经济系统构建
  • BeckHoff -->电脑与PLC连接
  • 今天做的力扣SQL
  • 基于FPGA的PID算法学习———实现P比例控制算法
  • 轻量级屏蔽文件管理方案
  • 深入浅出JavaScript中的ArrayBuffer:二进制数据的“瑞士军刀”
  • 端口扫描介绍及使用(学习笔记)
  • 苍穹外卖-day02
  • Profinet转CAN网关如何实现profinet与can协议互转
  • C++中auto和auto
  • 即梦图片 3.0 智能参考全量上线,开启 AI 设计零门槛新时代
  • 在 Windows 11 上创建新本地用户账户
  • 三元组 题解
  • 【Dv3Admin】系统视图登录日志API文件解析
  • qt 双缓冲案例对比
  • 做网站的需求清单/sem竞价培训班
  • 域名申请好了 怎么做网站/免费站推广网站2022
  • js做网站好吗/哪里可以做
  • 企业网站的首页设计/seo刷排名公司
  • 郑州直销网站制作/开通网站需要多少钱
  • 广州市酒店网站设计/智能建站