1)jwt的加密解密过程

jwt验证的核心就是加密解密的过程,掌握了这个过程,也就掌握了jwt的原理。jwt的三部分中,header和payload是明文的,能够直接读出来,签名Signature部分是进行了加密处理的。

Signature的加密过程

为了得到签名部分,你必须有编码过的header、编码过的payload、一个秘钥,签名算法是header中指定的那个,然对它们签名即可。一般的编码是base64url编码格式。

例如:

HMACSHA256(base64UrlEncode(header) + "." + base64UrlEncode(payload), secret)

签名是用于验证消息在传递过程中有没有被更改,并且,对于使用私钥签名的token,它还可以验证JWT的发送方是否为它所称的发送方。

解密方也会拿着秘钥对token最对应的解密,然后将解密的内容和原文内容做对比,如果一样就没有被篡改。

2)代码实现主要包含两部分,授权中心(token颁发),api服务器(验证token)

相对来说颁发token比较简单,上代码

[HttpPost]
public string Login()
{
var claims = new[]
{
new Claim(ClaimTypes.Name, "TestUser1"),
new Claim("Role","Administrator"),//传递其他信息
}; return CreateAccessToken(claims, _configuration);
} private string CreateAccessToken(IEnumerable<Claim> claims, IConfiguration configuration, TimeSpan? expiration = null)
{
var now = DateTime.UtcNow; var SecurityKey = new SymmetricSecurityKey(Encoding.ASCII.GetBytes(configuration["Authentication:JwtBearer:SecurityKey"])); var jwtSecurityToken = new JwtSecurityToken(
issuer: configuration["Authentication:JwtBearer:Issuer"],
audience: configuration["Authentication:JwtBearer:Audience"],
claims: claims,
notBefore: now,
expires: now.Add(expiration ?? TimeSpan.FromSeconds(configuration.GetValue<long>("Authentication:JwtBearer:Expiration"))),
signingCredentials: new SigningCredentials(SecurityKey, SecurityAlgorithms.HmacSha256)
); return new JwtSecurityTokenHandler().WriteToken(jwtSecurityToken);
}

这里只是省去了验证用户登录的过程,架设登录验证通过,直接生成token。

验证端相对代码逻辑会多一些,继续上代码:

public static void Configure(IServiceCollection services, IConfiguration configuration)
{
if (bool.Parse(configuration["Authentication:JwtBearer:IsEnabled"]))
{
string authenticationScheme = JwtBearerDefaults.AuthenticationScheme; services.AddAuthentication(authenticationScheme)
.AddJwtBearer(authenticationScheme, options =>
{
options.TokenValidationParameters = new TokenValidationParameters
{
SaveSigninToken = false,
ValidateActor = false,
ValidateTokenReplay = false, // The signing key must match!
RequireSignedTokens = true,
ValidateIssuerSigningKey = true,
IssuerSigningKey = new SymmetricSecurityKey(Encoding.ASCII.GetBytes(configuration["Authentication:JwtBearer:SecurityKey"])), // Validate the JWT Issuer (iss) claim
ValidateIssuer = true,
ValidIssuer = configuration["Authentication:JwtBearer:Issuer"], // Validate the JWT Audience (aud) claim
RequireAudience = true,
ValidateAudience = true,
ValidAudience = configuration["Authentication:JwtBearer:Audience"], // Validate the token expiry
RequireExpirationTime = true,
ValidateLifetime = true, // If you want to allow a certain amount of clock drift, set that here
ClockSkew = TimeSpan.Zero
};
});
}
}

这里面的配置信息和颁发端的配置要保持一致,否则无法验证通过。

验证端需要再控制器或者Action中加入验证,继续上代码

public void ConfigureServices(IServiceCollection services)
{
services.AddControllers(); //Jwt
AuthConfigurer.Configure(services, Configuration);
} // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
} #region jwt
//身份验证又称“认证”、“鉴权”,是指通过一定的手段,完成对用户身份的确认。
//身份验证的目的是确认当前所声称为某种身份的用户,确实是所声称的用户。
app.UseAuthentication();//注意添加这一句,启用验证
#endregion app.UseRouting(); //授权一般是指对信息安全或计算机安全相关的资源定义与授予访问权限,尤指访问控制。
//动词“授权”可指定义访问策略与接受访问。
//例如,人力资源人员通常被授权访问员工记录,而这个策略通常被形式化为计算机系统中的访问控制规则。
//在运行期间,系统使用已定义的访问控制规则决定是接受还是拒绝经过身份验证的访问请求。
app.UseAuthorization(); app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}

控制器访问限制:

[ApiController]
[Route("[controller]/[action]")]
//[Authorize]
public class BaseController : ControllerBase, IActionFilter
{
protected IEnumerable<Claim> claims { get; set; } public void OnActionExecuted(ActionExecutedContext context)
{ } public void OnActionExecuting(ActionExecutingContext context)
{
//claims = context.HttpContext.AuthenticateAsync().Result.Principal.Claims;//这种方式必须在控制器上方拥有[Authorize]特性时才可用
claims = context.HttpContext.User.Claims;
}
} [ApiController]
[Route("[controller]/[action]")]
[Authorize]
public class PatientController : BaseController
{
private readonly ILogger<PatientController> _logger; public PatientController(ILogger<PatientController> logger)
{
_logger = logger;
} [AllowAnonymous]
[HttpGet]
public async Task<string> GetByPatientId(long patientId)
{
return await Task.FromResult($"GetByPatientId:{patientId}");
} [HttpPost]
public async Task<Patient> CreateorUpdatePatient([FromBody] Patient patient)
{
var claims = this.claims;
patient.PatientName = "PatientName";
return await Task.FromResult(patient);
}
}

这里我们自定义了一个控制器的基类,实现了接口IActionFilter的两个方法,在控制器执行中,先执行了 OnActionExecuting,这里面可以获得token中的所有Claims,两种方法见代码,一种是直接使用

HttpContext.User.Claims

一种是在控制器拥有[Authorize]特性,然后可以使用

HttpContext.AuthenticateAsync().Result.Principal.Claims;

综上,jwt就可以实现了。至于过期时候刷新token,异地登录之后本地token失效等逻辑,单纯的依靠jwt是无法实现的,有想法的同学欢迎探讨。

附代码(支持国产):demo

03-Jwt在.netcore中的实现的更多相关文章

  1. .NetCore中的日志(2)集成第三方日志工具

    .NetCore中的日志(2)集成第三方日志工具 0x00 在.NetCore的Logging组件中集成NLog 上一篇讨论了.NetCore中日志框架的结构,这一篇讨论一下.NetCore的Logg ...

  2. .NetCore中的日志(1)日志组件解析

    .NetCore中的日志(1)日志组件解析 0x00 问题的产生 日志记录功能在开发中很常用,可以记录程序运行的细节,也可以记录用户的行为.在之前开发时我一般都是用自己写的小工具来记录日志,输出目标包 ...

  3. AutoMapper在asp.netcore中的使用

    # AutoMapper在asp.netcore中的使用  automapper 是.net 项目中针对模型之间转换映射的一个很好用的工具,不仅提高了开发的效率还使代码更加简洁,当然也是开源的,htt ...

  4. netcore中的缓存介绍

    Cache(缓存)是优化web应用的常用方法,缓存存放在服务端的内存中,被所有用户共享.由于Cache存放在服务器的内存中,所以用户获取缓存资源的速度远比从服务器硬盘中获取快,但是从资源占有的角度考虑 ...

  5. 在netcore中如何注入同一个接口的多个实现

    netcore中自带了Ioc框架,这也影响了我们的编码习惯,以前都是静态类或者直接new对象,现在有了Ioc框架的支持,我们也不必守旧,应当使用起来,接受这种对象管理方式.使用过java的同仁,都习惯 ...

  6. .NetCore中EFCore的使用整理(二)-关联表查询

    EF常用处理关联加载的方式有3中:延迟加载(Lazy Loading).贪婪加载 (Eager Loading)以及显示加载. 一.EF Core  1.1 1.当前的版本,还不支持延迟加载(Lazy ...

  7. .NetCore中EFCore for MySql整理(三)之Pomelo.EntityFrameworkCore.MySql

    一.Pomelo.EntityFrameworkCore.MySql简介 Git源代码地址:https://github.com/PomeloFoundation/Pomelo.EntityFrame ...

  8. .NetCore中如何实现权限控制 基于Claim角色、策略、基于Claim功能点处理

    .NetCore中如果实现权限控制的问题,当我们访问到一个Action操作的时候,我们需要进行权限控制 基于claims 角色控制 基于角色控制总觉得范围有点过大,而且控制起来感觉也不是太好,举一个例 ...

  9. .NetCore中EFCore for MySql整理(二)

    一.简介 EF Core for MySql的官方版本MySql.Data.EntityFrameworkCore 目前正是版已经可用当前版本v6.10,对于以前的预览版参考:http://www.c ...

  10. NetCore中使用Myrmec

    NetCore中使用Myrmec Myrmec 是什么? Myrmec 是一个用于检测文件格式的库,Myrmec不同于其它库或者手写检测代码,Myrmec不依赖文件扩展名(在实际使用中,你的用户很可能 ...

随机推荐

  1. springboot 和spring cloud 博客分享

    spring boot 知识点总结 天狼星 https://www.cnblogs.com/wjqhuaxia/p/9820902.html spring cloud 知识点总结 姿势帝 https: ...

  2. 深入浅出Mybatis系列(三)---配置简介(mybatis源码篇)

    上篇文章<深入浅出Mybatis系列(二)---Mybatis入门>写了一个Demo简单体现了一下Mybatis的流程.本次,将简单介绍一下Mybatis的配置文件: 上次例子中,我们以  ...

  3. 【springcloud】一文带你搞懂API网关

    作者:aCoder2013 https://github.com/aCoder2013/blog/issues/35 前言 假设你正在开发一个电商网站,那么这里会涉及到很多后端的微服务,比如会员.商品 ...

  4. vim conf文件配色

    VIM conf文件配色 一.配置文件 1.下载Nginx配置文件的语法文件:nginx.vim wget http://www.vim.org/scripts/download_script.php ...

  5. Java锁--Lock实现原理(底层实现)

    关于java lock的底层实现原理,讲的有点深,转载学习! 转载自 https://blog.csdn.net/Luxia_24/article/details/52403033 Lock完全用Ja ...

  6. 关于oracle样例数据库emp、dept、salgrade的mysql脚本复杂查询分析

    大家可以自行网上找资源(网上资源比较多,不建议下载我的),也可以在我这里下载: 1.取得每个部门最高薪水的人员名称:正确   一共有4个单位,要进行左外连接 其中一个单位没得员工 SELECT dep ...

  7. 【Azure 应用服务】使用PowerShell脚本上传文件至App Service目录  

    问题描述 使用PowerShell脚本上传文件至App Service目录的示例 脚本示例 对文件进行上传,使用的 WebClient.UploadFile 方法进行上传.当文件夹中包含子目录,执行以 ...

  8. centos 搭建jenkins+git+maven

      git+maven+jenkins持续集成搭建 发布人:[李源]  2017-12-08 04:33:37   一.搭建说明 系统:centos 6.5 jdk:1.8.0_144 jenkins ...

  9. 【Spring 5.x】学习笔记汇总

    Spring 工厂 工厂设计模式.第一个Spring程序细节分析.整合日志框架 注入详解 - Set注入(JDK内置类型,用户自定义类型).构造注入(重载) 反转控制与依赖注入.Spring工厂创建复 ...

  10. tomcat配置启动不了

    关于ideatomcat配置问题 1.第一步配置tomcat启动器 2.配置启动的网址 3.配置启动器的启动 ---更多java学习,请见本人小博客:https://zhangjzm.gitee.io ...