1.JWT简介

  官方定义:JWT是JSON Web Token的缩写,JSON Web Token是一个开放标准(RFC 7519),它定义了一种紧凑的、自包含的方式,可以将各方之间的信息作为JSON对象安全地传输。该信息可以被验证和信任,因为它是经过加密的。

  实际上,Oauth2.0中的access token一般就是jwt格式。

  token由三部分组成,通过"."分隔,分别是:

  ● 标头

  ● 有效载荷

   ● 签名

  所以JWT表示为:aaaaa.bbbbb.ccccc组成。

  1)标头,Header通常由两部分组成:使用的加密算法 "alg" 以及Token的种类 "typ"。如下:

  

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

  此JSON被Base64Url编码以形成JWT的第一部分。

  2)有效荷载,Payload主要包含了声明Claims,声明实际就是key:value数据,主要包含以下三种声明:

  Registered Claims: 注册声明,为IANA JSON Web Token 注册表中预先定义好的声明,这些声明非强制性,但是建议使用,如

  • ●  iss(issuer):签发人

    ●  exp(expiration time) :过期时间

    ●  sub(subject):主题

    ●  aud(audience):受众

    ●  nbf(not befaore):生效时间

    ●  lat(issued at):签发时间

    ●  jti(jwt id):编号

  Public Claims:公共声明,名称可以被任意定义。为了防止重复,任何新的Claim名称都应该被定义在IANA JSON Web Token Registry中或者使用一个包含不易重复命名空间的URI。

  Private Claims:私有声明,是在团队中约定使用的自定义Claims,既不属于Registered也不属于Public。

  此JSON进行Base64Url编码形成JWT的第二部分

  3)Signature,签名是将第一部分(header)、第二部分(payload)、密钥(key)通过指定算法(HMAC、RSA)进行加密生成的。

  

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

生成的签名就是JWT的第三部分。

将这三部分拼接在一起并使用"."分隔后形成的字符串就是Token。如:

可以使用jwt.io的Debugger解码,验证或生成JWT。

注意:虽然签名过后的Token可以防止篡改,但是Token的信息是公开的,任何人都可以读取,所以尽量不要在有效载荷或标头传递敏感信息(如密码)。

2.使用场景

1)目前来说,几乎所有之前使用cookie,session的地方,都可以换成jwt。

2)标准的对C或者对B的微服务系统,这个和之前讲的Oauth2.0协议最大的不同之处,jwt只是一个传输令牌,oauth2.0是一个授权协议,jwt可以理解为是oauth2.0的一部分。。。

3)信息安全交换,由于签名防篡改机制,可以验证其发行人和收件人。

3.Jwt的优势

1)无需存储,无服务器压力,轻量级使用,简单上手。

2)无视跨域,可多端使用,不像cookie、session依赖浏览器。

4.前端滑动登录状态管理方案

jwt token的过期时间如果短了,很影响前端用户操作体验,所以一般情况都是中长期的,以前的session管理登录状态,是滑动的,而现在jwt是无状态的,那么怎么才能做到滑动管理呢,具体细节分析请看这篇文章.NET Core WebAPI 认证授权之JWT(四):JWT续期问题 - 不落阁 (leo96.com) ,虽然没有解决,但是问题抛出的很细致,,我来说说我们现在正在使用的方案。

其实也很简单,用户请求后端服务数据时,作为有效动作,并且触发2小时的计时器,没到2小时的定时器清除并且重新启动,如果2小时内用户没有任何动作,认为是可以退出登录。

5..net core使用jwt

nuget安装System.IdentityModel.Tokens.Jwt

新建一个service写一个生成token的方法

 public class TokenService : ITokenService
{
private IConfiguration configuration; public TokenService(IConfiguration configuration)
{
this.configuration = configuration;
} public async Task<string> MakeJwtToken(long userId)
{
var claims = new[]
{
 // 角色需要在这里填写
         new Claim(ClaimTypes.Role, "Admin"),
         // 多个角色可以重复写,生成的 JWT 会是一个数组
new Claim(ClaimTypes.Role, "SuperAdmin"),
//其他声明
new Claim("uid", userId.ToString())
};
//私钥,验证方也需要使用这个进行验证。
var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(configuration["Auth:SecurityKey"]));
//加密方式
var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
var token = new JwtSecurityToken(
issuer: "AESCR",//发行人
audience: "AESCR",//接收人
claims: claims,
expires: DateTime.Now.AddMonths(30),//过期时间
signingCredentials: creds);
var res = new JwtSecurityTokenHandler().WriteToken(token);
return await Task.FromResult<string>(res);
}
}

启动类认证注入

services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(options => {
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = true,//是否验证发行人
ValidateAudience = true,//是否验证收件人
ValidateLifetime = true,//是否验证失效时间
ValidateIssuerSigningKey = true,//是否验证SecurityKey
ValidAudience = "AESCR",//Audience
ValidIssuer = "AESCR",//Issuer,这两项和后面签发jwt的设置一致
ClockSkew = TimeSpan.Zero, // // 默认允许 300s 的时间偏移量,设置为0
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Configuration["Auth:SecurityKey"]))//与创建者密钥一致
};
});
  app.UseAuthentication();//添加认证中间件

控制器代码

/// <summary>
/// 编辑用户信息
/// </summary>
/// <param name="userId"></param>
/// <param name="command"></param>
/// <returns></returns>
[HttpPost("{userId}/edit/userInfo")]
[ProducesResponseType(typeof(Users), (int)HttpStatusCode.OK)]
[ProducesResponseType(typeof(string), (int)HttpStatusCode.BadRequest)]
[Authorize]//token认证标签,如果需要角色认证,[Authorize(Roles ="admin")]
public async Task<IActionResult> EditUserInfo([FromRoute] long userId, [FromBody] EditUserInfoCommand command)
{
if (!this.CheckUser(command.UserId))
return BadRequest("您没有权限访问"); var result = await userService.EditUserInfo(command);
if (!result.IsSuccess)
return BadRequest(result.FailureReason);
return Ok(result.GetData());
}

以上代码就完事了,简单吧,在请求的时候,带上token就可以了。

这里有一个细节问题,由于我们这里用户ID,都是在jwt的Payload中,那么是否还需要请求接口的时候在参数中传输呢?个人理解是这样:

1.首先先看下token验证过后,怎么取claims的声明

 public static class ControllerExtensions
{
public static long GetUserId(this ControllerBase controllerBase)
{
var claim = controllerBase.User.Claims.Where(p => p.Type == "uid").FirstOrDefault();
if (claim == null)
return 0;
long res = 0;
long.TryParse(claim.Value, out res);
return res;
} public static bool CheckUser(this ControllerBase controllerBase, long userId)
{
return controllerBase.GetUserId() == userId;
}
}

我可以从payload中获取到创建token时带进去的用户id---uid,回到问题,我认为即使可以拿到用户ID,也需要从接口参数中传递过来,因为安全认证是一个切面拦截,我们的服务如果去掉切面,要保障正常运行,我们只需要在加一个传递参数中的uid和声明里的uid是否一致,来判断是否是当前用户的操作。

微服务系列之授权认证(三) JWT的更多相关文章

  1. 微服务系列之授权认证(一) OAuth 2.0 和 OpenID Connect

    1.传统架构的授权认证 传统应用架构,用户使用账号密码登录后,可以使用前端cookie存储登录状态,也可以使用后端session方式存储登录状态,小应用这么做其实很高效实用,当应用需要横向扩展时,就需 ...

  2. 微服务系列之授权认证(二) identity server 4

    1.简介 IdentityServer4 是为ASP.NET Core系列量身打造的一款基于 OpenID Connect 和 OAuth 2.0 认证授权框架. 官方文档:https://ident ...

  3. 【CHRIS RICHARDSON 微服务系列】微服务架构中的进程间通信-3

    编者的话 |本文来自 Nginx 官方博客,是微服务系列文章的第三篇,在第一篇文章中介绍了微服务架构模式,与单体模式进行了比较,并且讨论了使用微服务架构的优缺点.第二篇描述了采用微服务架构的应用客户端 ...

  4. 【转】「Chris Richardson 微服务系列」微服务架构的优势与不足

    Posted on 2016年5月4日 编者的话|本文来自 Nginx 官方博客,是微服务系列文章的第一篇,主要探讨了传统的单体式应用的不足,以及微服务架构的优势与挑战. 作者介绍:Chris Ric ...

  5. 微服务系列(二):使用 API 网关构建微服务

    编者的话|本文来自 Nginx 官方博客,是微服务系列文章的第二篇,本文将探讨:微服务架构是如何影响客户端到服务端的通信,并提出一种使用 API 网关的方法. 作者介绍:Chris Richardso ...

  6. Spring Cloud微服务系列文,服务调用框架Feign

    之前博文的案例中,我们是通过RestTemplate来调用服务,而Feign框架则在此基础上做了一层封装,比如,可以通过注解等方式来绑定参数,或者以声明的方式来指定请求返回类型是JSON.    这种 ...

  7. 微服务系列实践 .NET CORE

    从事这个行业转眼已经6年了,从当初刚毕业的在北京朝八晚十,从二环到五环,仍每天精力充沛的小愤青:再到深圳一点一滴的辛勤在软件行业的耕种,从当初单体应用架构到现在微服务架构的经历,回想起来自己的收获倒是 ...

  8. 微服务指南走北(三):Restful API 设计简述

    API的定义取决于选择的IPC通信方式,假设是消息机制(如 AMQP 或者 STOMP).API则由消息频道(channel)和消息类型.假设是使用HTTP机制,则是基于请求/响应(调用http的ur ...

  9. 【CHRIS RICHARDSON 微服务系列】事件驱动的数据管理-5

    编者的话 |本文来自 Nginx 官方博客,是「Chris Richardson 微服务」系列的第五篇文章.第一篇文章介绍了微服务架构模式,并且讨论了使用微服务的优缺点:第二和第三篇描述了微服务架构模 ...

随机推荐

  1. vmstate 命令详解2022

    vmstat 是一个查看虚拟内存(Virtual Memory)使用状况的工具,但是怎样通过 vmstat 来发现系统中的瓶颈呢? 1. 使用vmstat 使用前我们先看下命令介绍及参数定义 Usag ...

  2. 升级了Springboot版本后项目启动不了了

    问题背景 项目上使用的springboot版本是2.1.1.RELEASE,现在因为要接入elasticsearch7.x版本,参考官方文档要求,需要将springboot版本升级到2.5.14. 本 ...

  3. day02 Java_变量

    参考: 变量的练习: 声明一个变量,一次声明多个变量. 声明变量直接初始化,先声明变量,而后再给变量初始化. 声明整型变量g,声明另一个整型变量h并赋值为h+10,输出变量h的值. 声明整型变量i,在 ...

  4. jdbc 03:注册驱动的方式

    jdbc连接mysql时,注册驱动的方式 package com.examples.jdbc.o3_注册驱动方式; //mysql驱动所在的包 import com.mysql.jdbc.Driver ...

  5. 定时脚本删除docker容器中内容

    今天在我同步mongo数据库的时候,服务器的磁盘突然就被占满了导致同步中断,mongo容器也停止工作了.然后就想要弄一个能够定时清理同步过程中留存在docker容器中的mongo数据的脚本.话不多说, ...

  6. HMS Core音频编辑服务音源分离与空间音频渲染,助力快速进入3D音频的世界

    从单声道.立体声.环绕声发展到三维声,音频回放技术的迭代演进是为了还原真实世界的声音.其中,三维声技术使用信号处理的方法对到达两耳的声音信号进行模拟,将声场还原为三维空间,更接近真实世界.凭借这个技术 ...

  7. 使用Mpvue配合Weui开发面试题题库微信小程序,并且发布到正式环境

    原文转载自「刘悦的技术博客」https://v3u.cn/a_id_116 之前的一篇文章详细阐述了微信小程序开发的准备和入门以及环境搭建,这一次我们介绍如何将微信小程序如何上线,同时配合weui美化 ...

  8. 如何给MySQL添加自定义语法 ?

    目录 1 背景 2 新增关键词(token) 3 新增语法 4 类似于PT_partition添加对应的数据结构global_partition_clause 1 背景 MySQL语法解析器用的bis ...

  9. Ubuntu14.04或16.04下普通用户的root权限获得

    Ubuntu系统默认不允许使用root登录,因此初始root帐户是不能使用的,需要在普通账户下利用sudo权限修改root密码.然后以root帐户进行相关操作. 具体操作: 1.打开系统,用普通帐户登 ...

  10. 新一代大数据任务调度系统 - Apache DolphinScheduler 1.3.4 发布,推荐下载

    | 本文编辑:朱桐 新一代大数据任务调度 - Apache DolphinScheduler(incubator) 在经过社区 30 多位小伙伴的贡献与努力下于发布了 1.3.4 版本,1.3.4 作 ...