首页 > 编程语言 >asp.net core api 基于token的JWT bearer 的鉴权验证实现探索

asp.net core api 基于token的JWT bearer 的鉴权验证实现探索

时间:2022-11-24 22:34:22浏览次数:48  
标签:core asp bearer app audience token new true issuer


.net的各种框架啥的都不是很熟悉,当时只是想怎么实现快速校验授权确保api是通过验证之后才能打开。
我说的快速就是不需要写重复的样板代码,通过总体控制,最后发现,似乎也只能通过注解实现,不过也算是比较合理的,不然无法区分哪些需要哪些不需要了

那么实现原理就设计到cookie,session, token,前面的session是需要服务器存档用户信息的,服务器压力比较大,token的实现原理,在登录之后返回 一个token, 之后再每一个接口提交都传递token,

都传递token可以通过请求头提交也可以通过get,post这些提交,我这里探索两者均实现。

问了一些网友,说要实现便捷授权可以实现拦截器,拦截器类似注解,
那么只是单纯的拦截器还不是根本,而且我还是没看懂所以然咋自己通过写拦截器代码实现,
最后不得不直接用框架jwt bearer实现

jwt bearer 接入是只需要添加注解Auth 就可以实现对指定方法的鉴权。

using coreapiauth;
using coreapiauth.TestWebApi.AuthCenter.Utility;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.IdentityModel.Tokens;
using System.Text;

var builder = WebApplication.CreateBuilder(args);



// Add services to the container.

builder.Services.AddControllers();
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
//注入JWT服务
builder.Services.AddScoped<IJwtService, JwtService>();


#region 注册JWT鉴权
var issuer = "study"; //Configuration["issuer"];
var audience = "lozn"; //Configuration["audience"];
var securityKey = "4A9A70D2-B8AD-42E1-B002-553BDEF4E76F";// Configuration["SecurityKey"];


//配置认证服务
builder.Services.AddAuthentication(x =>
{
x.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
x.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
});

builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme) //默认授权机制名称
.AddJwtBearer(options =>
{


options.TokenValidationParameters = new TokenValidationParameters();
options.Events = new JwtBearerEvents()
{
OnMessageReceived = context =>
{
context.Token = context.Request.Query["access_token"];
return Task.CompletedTask;
}
};
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = true, //是否验证Issuer
ValidateAudience = true, //是否验证Audience
ValidateLifetime = true, //是否验证失效时间
RequireExpirationTime = true, //过期时间
ValidateIssuerSigningKey = true, //是否验证IssuerSigningKey
ValidAudience = audience,
ValidIssuer = issuer,
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(securityKey)),
//自定义校验规则:新登录后,之前的token无效
//AudienceValidator = (audiences, securityToken, validationParameters) =>
//{
// return audiences != null && audiences.FirstOrDefault().Equals(audience);
//}
};
});
#endregion


var app = builder.Build();

// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
}


//app.UseHttpsRedirection();


//1.先开启认证
app.UseAuthentication();
//2.再开启授权
app.UseAuthorization();



app.MapControllers();

app.Run();

网上的文章似乎有些将的不是 core api,有些是core api,但是和我这边开发工具生成的模板代码又不一样,所以我这边是这样子的。
其中

app.UseAuthentication();
app.UseAuthorization();

似乎影响了最后能否正常通过鉴权,我之前是成功获取了token,但是一直卡无法鉴权成功, 请求头应该传递什么,最后得出的结论:​​Authorization​​​为请求头的key ,value为​​Bearer 登录返回的key​​ 也可以通过get提交,上面的完整代码之所以可以get生效是因为有如下代码生效

options.Events = new JwtBearerEvents()
{
OnMessageReceived = context =>
{
context.Token = context.Request.Query["access_token"];
return Task.CompletedTask;
}
};

那么访问

http://lozn.vaiwan.com/api/Auth/GetAuthData?access_token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCIsImN0eSI6IkpXVCJ9.eyJodHRwOi8vc2NoZW1hcy54bWxzb2FwLm9yZy93cy8yMDA1LzA1L2lkZW50aXR5L2NsYWltcy9uYW1lIjoiYWRtaW4iLCJOaWNrTmFtZSI6Ik5ldENvcmUiLCJSb2xlIjoiQWRtaW5pc3RyYXRvciIsImV4cCI6MTY1NDA3MDY2NywiaXNzIjoic3R1ZHkiLCJhdWQiOiJsb3puIn0.7GQOQybhFLFXpL0FO31WNdm-o8MYJHS5F-y1xB-PQPU

我写的这个源码有两个地方都用到了秘钥,

其中在启动的代码中配置的是如下

options.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = true, //是否验证Issuer
ValidateAudience = true, //是否验证Audience
ValidateLifetime = true, //是否验证失效时间
RequireExpirationTime = true, //过期时间
ValidateIssuerSigningKey = true, //是否验证IssuerSigningKey
ValidAudience = audience,
ValidIssuer = issuer,
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(securityKey)),
//自定义校验规则:新登录后,之前的token无效
//AudienceValidator = (audiences, securityToken, validationParameters) =>
//{
// return audiences != null && audiences.FirstOrDefault().Equals(audience);
//}
};

而在登录的时候返回 token用到的代码

public string GetToken(string name)
{
/**
* Claims(Payload)
* Claims包含了一些跟这个token有关的重要信息。JWT标准规定的字段:
*
* iss: The issuer of the token, 签发人
* sub: The subject of the token, 主题
* exp: Expiration Time. 过期时间(Unix时间戳格式)
* iat: Issued At. 签发时间(Unix时间戳格式)
* jti: JWT ID. 编号
* aud: audience. 受众
* nbf: Not Before. 生效时间
*
* 除了规定的字段外,可以包含其他任何JSON兼容的字段。
* */
var claims = new[]
{
new Claim(ClaimTypes.Name, name),
new Claim("NickName", "NetCore"),
new Claim("Role", "Administrator")
};


if (_configuration["SecurityKey"] == null)
{
throw new Exception("please config SecurityKey issuer audience at appsettings.json");

}

var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_configuration["SecurityKey"]));
var credentials = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);

var token = new JwtSecurityToken(
issuer: _configuration["issuer"], //签发人
audience: _configuration["audience"],
claims: claims,
expires: DateTime.Now.AddMinutes(20), //20分钟有效期
signingCredentials: credentials);
var tokenStr = new JwtSecurityTokenHandler().WriteToken(token);
return tokenStr;
}

如果两者的issuer,audience,或者key不一致,一样是无法鉴权成功的,为了确保 SecurityKey在appsetting.json里面定义我直接加了检测,不存在直接抛出异常。
就可以成功实现访问,而非返回401,如果鉴权不成功是返回401的
最后能成功实现,还是参考了如下比较有参考意义的文章,前者并没有提到怎么去传递请求头,以及configuration参数怎么传递也没提及,所以搞的我一直没成功,
完整源码暂时不放出来了,因为第一篇文章已经算文章了,而我提供的program.cs也解决了如何读取configration的问题,以及写了一篇关于配置文件configration是啥玩意的问题。

标签:core,asp,bearer,app,audience,token,new,true,issuer
From: https://blog.51cto.com/u_15458814/5885127

相关文章

  • golang coredump
    golang生成coredump文件refer:   https://blog.csdn.net/xmcy001122/article/details/105665732   http://t.zoukankan.com/lit10050528-p-4811833.html1.设置cor......
  • @Aspect 注解使用详解
    AOP为AspectOrientedProgramming的缩写,意为:面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术.AOP是​​OOP​​​的延续,是软件开发中的一个......
  • MassTransit - .NET Core 的分布式应用程序框架
    简介MassTransit是一个免费的、开源的.NET分布式应用程序框架。MassTransit使创建应用程序和服务变得容易,这些应用程序和服务利用基于消息的松散耦合异步通信来实现更......
  • EFCore DBFirst从数据库生成实体类
    目录EFCoreDBFirst从数据库生成实体类官网安装指定NuGet包生成实体类EFCoreDBFirst从数据库生成实体类本示例仅适用于mysql版本,其他版本请根据官网说明进行操作。官网......
  • Aspose.Cells实现excel预览
    ​在WEB项目中经常遇到excel文档在线预览的需求,基本的解决思路有以下几大类:excel文档转PDF、excel文档直接转html、后台读取excel数据返回给前端利用Excel效果的表格插件......
  • .NET Core读写InfluxDB时序数据库的方法教程
    前言在我们很多应用中会遇到有一种基于一系列时间的数据需要处理,通过时间的顺序可以将这些数据点连成线,再通过数据统计后可以做成多纬度的报表,也可通过机器学习来实现数据......
  • 接口认证方式:Bearer Token
    因为HTTP协议是开放的,可以任人调用。所以,如果接口不希望被随意调用,就需要做访问权限的控制,认证是好的用户,才允许调用API。此文介绍下目前主流的访问权限控制/认证模......
  • ASP .NET Core 缓存
    缓存可以通过减少生成内容所需的工作,显著提高应用的性能和可伸缩性。缓存最适用于不常更改且生成成本很高的数据。缓存生成的数据副本可以比从源中更快地返回。应该以从......
  • EFCore-实体关系配置
    EFCore-实体关系配置EFCore中实体之间关系的配置的套路:HasXXX(…).WithXXX(…);有XXX、反之带有XXX。XXX可选值One、Many。一对多:HasOne(…).WithMany(…);一对一:H......
  • EF Core迁移失败 ,It was not possible to find any compatible framework version
    前言:其实我很早之前就知道可以这样做,但是现在遇到这个错误,我忘记了答案。所以还是记录下来吧。。。。。参考链接:https://learn.microsoft.com/en-us/answers/questio......