之前在公司的项目中有用到jwt进行token验证,但是公司里用的框架已经集成好了jwt,所以对jwt的的了解不够清晰,感觉还是隔着一层。在看了“老张的哲学”的jwt部分后对jwt的认识才更加深刻了一些,这篇文章主要是自己对知识的一个梳理。

  1.   Jwt的介绍
  2. swagger中启用jwt
  3. 配置jwt官方认证 
  4. 例子

1、jwt的组成

jwt通常由三部分组成,(1)头部 Header、(2)消息载体 payload、(3)签名 signature   由.号隔开三部分  例如

  eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ

1)Header一般由两个部分组成:alg和typ

   alg是所使用的hash算法,如:HMAC SHA256或RSA,typ是Token的类型,在这里就是:JWT,然后使用Base64Url编码成第一部分:

  eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.
{
"alg": "HS256",
"typ": "JWT"
}

2)payload这一部分是JWT主要的信息存储部分,主要由各种claims(声明/信息)组成

   在JwtRegisteredClaimNames(微软预先定义的)类中包含了一些常用的信息,例如:Jti(编号)、Iat(签发时间)、Exp(过期时间)、Iss(签发人)、Aud(订阅者)等

    一个简单的Pyload可以是这样子的,同样使用Base64Url编码成第二部分::

  eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.
{
"sub": "1234567890",
"name": "John Doe",
"admin": true
}

  3)signature 签名,通过服务端的密钥生成,用来验证生成的jwt是不是有效的,最后生成的jwt

    eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ

 2、Swagger中启用jwt 注意是swagger服务内部

 api文档用的是swagger,所以还需要在startup里的swagger配置中启用jwt的配置,swagger的具体配置使用就不放在这边,准备以后结合公司的方式在补充一篇。 

  在ConfigureServices下的swagger中配置jwt

          #region Swagger

            services.AddSwaggerGen(c =>
{
#region swagger的配置 c.SwaggerDoc("v1",new Info
{
Version = "v0.1.0",
Title = "Blog.Core API",
Description = "框架说明文档"
});
var basePath = Microsoft.DotNet.PlatformAbstractions.ApplicationEnvironment.ApplicationBasePath;
var xmlPath = Path.Combine(basePath, "Blog.Core.xml");
c.IncludeXmlComments(xmlPath,true);//默认的第二个参数是false,这个是controller的注释,记得修改 var xmlModelPath = Path.Combine(basePath, "Blog.Core.Model.xml");
c.IncludeXmlComments(xmlModelPath);
#endregion #region swagger 中开启jwt认证
//添加header验证信息
var security = new Dictionary<string, IEnumerable<string>> { { "Blog.Core", new string[] { } } };
c.AddSecurityRequirement(security);
c.AddSecurityDefinition("Blog.Core", new ApiKeyScheme
{
Description = "JWT授权(数据将在请求头中进行传输) 直接在下框中输入Bearer {token}(注意两者之间是一个空格)",
Name = "Authorization",
In = "header",
Type = "apiKey"
}); #endregion }); #endregion

3、配置官方jwt

在swagger开启jwt认证后,还需要配置jwt中间件(用来解析收到jwt是否有效),我用的官方默认配置

在appsettings.json中的配置(可以改进,感觉还是根据环境变量配置比较好即放入(appsettings.Development.json)文件中,中间的Development根据环境改变)

  "Audience": {
"Secret": "sdfsdfsrty45634kkhllghtdgdfss345t678fs", //不要太短,请注意!!!16+
"SecretFile": "C:\\my-file\\blog.core.audience.secret.txt",
"Issuer": "Blog.Core",
"Audience": "wr"
}  

在ConfigureServices中配置

      #region jwt 官方认证
//密钥的生成
var audienceConfig = Configuration.GetSection("Audience");
var symmetricKeyAsBase64 = audienceConfig["Secret"]; //从配置中读取密钥 注意:密钥长度需要大于16位
var KeyByteArray = Encoding.UTF8.GetBytes(symmetricKeyAsBase64);
var signingKey = new SymmetricSecurityKey(KeyByteArray); // 令牌验证参数
var tokenValidationParameters = new TokenValidationParameters
{
ValidateIssuerSigningKey = true,
IssuerSigningKey = signingKey,
ValidateIssuer = true,
ValidIssuer = audienceConfig["Issuer"],//发行人
ValidateAudience = true,
ValidAudience = audienceConfig["Audience"],//订阅人
ValidateLifetime = true,
RequireExpirationTime = true,
}; //主要部分
services.AddAuthentication("Bearer")
.AddJwtBearer(option =>
{
option.TokenValidationParameters = tokenValidationParameters;
}); #endregion

  

在configure 中配置,启用jwt官方中间件

 //如果你想使用官方认证,必须在上边ConfigureService 中,配置JWT的认证服务 (.AddAuthentication 和 .AddJwtBearer 二者缺一不可)
app.UseAuthentication();

  4、例子

在配置完成之后服务端需要提供一个GetToken(获取生成的jwt)的方法给前端,在需要使用认证的接口加上特性标签表示启用检测jwt是否有用

例(老方法,之后有空了补充新的生成jwt方法,加上refreshToken,避免token过期问题):

    [Route("api/Blog")]
[Authorize]
public class BlogController : Controller
{
// GET: api/Blog/5
[HttpGet("GetToken")]
[AllowAnonymous]
public string GetToken()
{
TokenModelJwt tokenModel = new TokenModelJwt
{
Role="Admin",
Uid=1,
Work=""
};
return JwtHelper.IssueJwt(tokenModel); ;
}
}

  

      /// <summary>
/// 颁发token
/// </summary>
/// <param name="tokenModel"></param>
/// <returns></returns>
public static string IssueJwt(TokenModelJwt tokenModel)
{
// 自己封装的 appsettign.json 操作类,看下文
string iss = Appsettings.app(new string[] { "Audience", "Issuer" }); //iss: 签发人
string aud = Appsettings.app(new string[] { "Audience", "Audience" });//aud: 受众
string secret = Appsettings.app(new string[] { "Audience", "Secret" }); var claims = new List<Claim>
{
new Claim(JwtRegisteredClaimNames.Jti,tokenModel.Uid.ToString()),//jti: 编号
new Claim(JwtRegisteredClaimNames.Iat,$"{new DateTimeOffset(DateTime.Now).ToUnixTimeMilliseconds()}"),//Iat 签发时间
//new Claim(JwtRegisteredClaimNames.Nbf,$"{new DateTimeOffset(DateTime.Now).ToUnixTimeMilliseconds()}"),//nbf: 生效时间
new Claim(JwtRegisteredClaimNames.Exp,$"{new DateTimeOffset(DateTime.Now.AddSeconds(1000)).ToUnixTimeMilliseconds()}"),//exp: 过期时间
//这个就是过期时间,目前是过期1000秒,可自定义,注意JWT有自己的缓冲过期时间
new Claim(JwtRegisteredClaimNames.Iss,iss),
new Claim(JwtRegisteredClaimNames.Aud,aud)
};
//// 可以将一个用户的多个角色全部赋予;
claims.AddRange(tokenModel.Role.Split(',').Select(e=>new Claim(ClaimTypes.Role,e)));
//秘钥 (SymmetricSecurityKey 对安全性的要求,密钥的长度太短会报出异常) var key=new SymmetricSecurityKey(Encoding.UTF8.GetBytes(secret));
var creds=new SigningCredentials(key,SecurityAlgorithms.HmacSha256); var jwt = new JwtSecurityToken(
issuer: iss,
audience: aud,
claims: claims,
expires:DateTime.Now.AddHours(1),
signingCredentials: creds); var jwtHandler = new JwtSecurityTokenHandler();
var encodedJwt = jwtHandler.WriteToken(jwt); return encodedJwt;
}

  补充Appsetings类(有空了修改更加简介的方式),使用记得去Startup里面注入,注入方法:services.AddSingleton(new Appsettings(Env.ContentRootPath));

  public class Appsettings
{
static IConfiguration Configuration { get; set; }
static string contentPath { get; set; } public Appsettings(string contentPath)
{
//如果你把配置文件 是 根据环境变量来分开了,可以这样写
string Path = $"appsettings.{Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT")}.json"; //string Path = "appsettings.json"; Configuration = new ConfigurationBuilder()
.SetBasePath(contentPath)
.Add(new JsonConfigurationSource {Path = Path, Optional = false, ReloadOnChange = true})
.Build();
} public static string app(params string[] sections)
{
try
{
if (sections.Any())
{
return Configuration[string.Join(":", sections)];
}
}
catch (Exception) { }
return "";
}
}

  最后,以上代码大部分使用的是“老张的哲学”Blog.Core项目的代码,个人学习使用,之后会修改掉,如有侵权请联系删除。

.netCore下的jwt的梳理-->借鉴于“老张的哲学”的更多相关文章

  1. .NetCore WebApi——基于JWT的简单身份认证与授权(Swagger)

    上接:.NetCore WebApi——Swagger简单配置 任何项目都有权限这一关键部分.比如我们有许多接口.有的接口允许任何人访问,另有一些接口需要认证身份之后才可以访问:以保证重要数据不会泄露 ...

  2. .NetCore 下开发独立的(RPL)含有界面的组件包 (六)实现业务功能

    .NetCore 下开发独立的(RPL)含有界面的组件包 (一)准备工作 .NetCore 下开发独立的(RPL)含有界面的组件包 (二)扩展中间件及服 务 .NetCore 下开发独立的(RPL)含 ...

  3. .NetCore 下开发独立的(RPL)含有界面的组件包 (五)授权过滤参数处理

    .NetCore 下开发独立的(RPL)含有界面的组件包 (一)准备工作 .NetCore 下开发独立的(RPL)含有界面的组件包 (二)扩展中间件及服 务 .NetCore 下开发独立的(RPL)含 ...

  4. .NetCore 下开发独立的(RPL)含有界面的组件包 (四)授权过滤

    .NetCore 下开发独立的(RPL)含有界面的组件包 (一)准备工作 .NetCore 下开发独立的(RPL)含有界面的组件包 (二)扩展中间件及服 务 .NetCore 下开发独立的(RPL)含 ...

  5. .NetCore 下开发独立的(RPL)含有界面的组件包 (三)构建界面

    .NetCore 下开发独立的(RPL)含有界面的组件包 (一)准备工作 .NetCore 下开发独立的(RPL)含有界面的组件包 (二)扩展中间件及服 务 .NetCore 下开发独立的(RPL)含 ...

  6. .NetCore 下开发独立的(RPL)含有界面的组件包 (二)扩展中间件及服务

    .NetCore 下开发独立的(RPL)含有界面的组件包 (一)准备工作 .NetCore 下开发独立的(RPL)含有界面的组件包 (二)扩展中间件及服 务 .NetCore 下开发独立的(RPL)含 ...

  7. .NetCore 下开发独立的(RPL)含有界面的组件包 (一)准备工作

    .NetCore 下开发独立的(RPL)含有界面的组件包 (一)准备工作 .NetCore 下开发独立的(RPL)含有界面的组件包 (二)扩展中间件及服 务 .NetCore 下开发独立的(RPL)含 ...

  8. NetCore下模拟和使用Modbus工业通信协议

    Tips: 1.目前NetCore下与Modbus通信的框架主要选择了 Modbus.Net  https://github.com/parallelbgls/Modbus.Net 2.modbus是 ...

  9. .netcore下的微服务、容器、运维、自动化发布

    原文:.netcore下的微服务.容器.运维.自动化发布 微服务 1.1     基本概念 1.1.1       什么是微服务? 微服务架构是SOA思想某一种具体实现.是一种将单应用程序作为一套小型 ...

随机推荐

  1. 关于Apache Commons的简介

    Apache Commons是对JDK的拓展,包含了很多开源的工具,用于解决平时编程经常会遇到的问题,减少重复劳动.官网网址:http://commons.apache.org Commons Bea ...

  2. Office Shared-Addin : Favorite的下载、安装和使用(2020.2.22)

    Favorite是一个可以用于Office常用组件.VBA的共用加载项,32位和64位都兼容. 如果是Office 2007及其以上版本,界面显示为Custom UI+任务窗格. 如果是Office ...

  3. Office 365管理中心门户

    一.使用Office 365管理员账户登陆到由世纪互联运营的Office 365 登陆地址 https://portal.partner.microsoftonline.cn 1.登陆完成后,选择左上 ...

  4. 吴裕雄--天生自然python学习笔记:python用 Selenium 组件实现浏览器操作自动化

    一般情况下,我们都是用手工操作的方式来对浏览器进行各种操作 . 实际上, 只要我们安装一个自动化操作组件, Python 就可以让我们的很多操作实现自动化 . Selenium 组件 在开发网页时,用 ...

  5. Oracle中实现sql查询得到连续号码段

    一.表名为t的表中数据如下: select * from t; FPHM KSHM ---------- ---------- 实现代码如下: select b.fphm,min(b.kshm),ma ...

  6. django项目导航页_20191128

    django项目导航页_20191128 第一步:python-django电商项目-需求分析架构设计数据库设计_20191115 python-django-linux上mysql的安装和配置_20 ...

  7. 牛客-小y的盒子

    题目传送门 -------------------稍加观察就会发现,4n - 1就是题目要的答案.至于为什么,看官方的题解.不过这个n非常的大,用正常快速幂解决不了.这道题我学到的就是解决幂非常大的情 ...

  8. LG_2286_[HNOI2004]宠物收养场

    题目描述 凡凡开了一间宠物收养场.收养场提供两种服务:收养被主人遗弃的宠物和让新的主人领养这些宠物. 每个领养者都希望领养到自己满意的宠物,凡凡根据领养者的要求通过他自己发明的一个特殊的公式,得出该领 ...

  9. ES6中 const 关键字

    const声明一个只读的常量.一旦声明,常量的值就不能改变. 定义后可以使用但不能修改 但是,const 定义的对象可能与我们想象的不太一样 定义了对象b ,我们可以在b上添加修改属性,再看一个列子 ...

  10. Kafka 安装及入门

    什么是Kafka? Kafka是由Apache软件基金会开发的一个开源流处理平台,由Scala和Java编写.Kafka是一种高吞吐量的分布式发布订阅消息系统,它可以处理消费者规模的网站中的所有动作流 ...