Loading [MathJax]/jax/output/CommonHTML/config.js
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >秒懂JWT

秒懂JWT

作者头像
喵叔
发布于 2020-09-08 08:32:33
发布于 2020-09-08 08:32:33
61500
代码可运行
举报
文章被收录于专栏:喵叔's 专栏喵叔's 专栏
运行总次数:0
代码可运行

JWT 英文名是 Json Web Token ,是一种用于通信双方之间传递安全信息的简洁的、URL安全的表述性声明规范,经常用在跨域身份验证。JWT 以 JSON 对象的形式安全传递信息。因为存在数字签名,因此所传递的信息是安全的。 在讲解 JWT 之前我们先来看一个问题。我们都知道 Internet 服务的身份验正过程是这样的,客户端向服务器发送登录名和登录密码,服务器验证后将对应的相关信息保存到当前会话中,这些信息包括权限、角色等数据,服务器向客户端返回 session ,session 信息都会写入到客户端的 Cookie 中,后面的请求都会从 Cookie 中读取 session 发送给服务器,服务器在收到 session 后会对比保存的数据来确认客户端身份。 但是上述模式存在一个问题,无法横向扩展。在服务器集群或者面向服务且跨域的结构中,需要数据库来保存 session 会话,实现服务器之间的会话数据共享。 在单点登录中我们会遇到上述问题,当有多个网站提供同一拨服务,那么我们该怎么实现在甲网站登陆后其他网站也同时登录呢?其中一种方法时持久化 session 数据,也就是上面所说的将 session 会话存到数据库中。这个方法的优点是架构清晰明了。但是缺点也非常明显,就是架构修改很困难,验证逻辑需要重修,并且整体依赖于数据库,如果存储 session 会话的数据库挂掉那么整个身份认证就无法使用,进而导致系统无法登录。要解决这个问题我们就用到了 JWT 。

零、JWT 简述

客户端身份经过服务器验证通过后,会生成带有签名的 JSON 对象并将它返回给客户端。客户端在收到这个 JSON 对象后存储起来。在以后的请求中客户端将 JSON 对象连同请求内容一起发送给服务器,服务器收到请求后通过 JSON 对象标识用户,如果验证不通过则不返回请求的数据。验证不通过的情况有很多,比如签名不正确、无权限等。在 JWT 中服务器不保存任何会话数据,使得服务器更加容易扩展。

一、Base64URL 算法

在讲解 JWT 的组成结构前我们先来讲解一下 Base64URL 算法。这个算法和 Base64 算法类似,但是有一点区别。我们通过名字可以得知这个算法使用于 URL 的,因此它将 Base64 中的 + 、 / 、 = 三个字符替换成了 - 、 _ ,删除掉了 = 。因为这个三个字符在 URL 中有特殊含义。

二、JWT 组成结构

JWT 是由三段字符串和两个 . 组成,每个字符串和字符串之间没有换行(类似于这样:xxxxxx.yyyyyy.zzzzzz),每个字符串代表了不同的功能,我们将这三个字符串的功能按顺序列出来并讲解:

1.JWT 头 JWT 头描述了 JWT 元数据,是一个 JSON 对象,它的格式如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
{
  "alg":"HS256",
  "typ":"JWT"
}

这里的 alg 属性表示签名所使用的算法,JWT 签名默认的算法为 HMAC SHA256 , alg 属性值 HS256 就是 HMAC SHA256 算法。typ 属性表示令牌类型,这里就是 JWT。 2. 有效载荷 有效载荷是 JWT 的主体,同样也是个 JSON 对象。有效载荷包含三个部分:

  • 标准注册声明 标准注册声明不是强制使用是的,但是我建议使用。它一般包括以下内容: iss:jwt的签发者/发行人; sub:主题; aud:接收方; exp:jwt过期时间; nbf:jwt生效时间; iat:签发时间 jti:jwt唯一身份标识,可以避免重放攻击
  • 公共声明 可以在公共声明添加任何信息,我们一般会在里面添加用户信息和业务信息,但是不建议添加敏感信息,因为公共声明部分可以在客户端解密。
  • 私有声明 私有声明是服务器和客户端共同定义的声明,同样这里不建议添加敏感信息。 下面这个代码段就是定义了一个有效载荷:
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
{
  "exp":"201909181230",
  "role":"admin",
  "isShow":false
}

2.哈希签名 哈希签名的算法主要是确保数据不会被篡改。它主要是对前面所讲的两个部分进行签名,通过 JWT 头定义的算法生成哈希。哈希签名的过程如下:

3.指定密码,密码保存在服务器中,不能向客户端公开;

4.使用 JWT 头指定的算法进行签名,进行签名前需要对 JWT 头和有效载荷进行 Base64URL 编码,JWT 头和邮箱载荷编码后的结果之间需要用 . 来连接。 简单示例如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
HMACSHA256(base64UrlEncode(JWT) + "." + base64UrlEncode(有效载荷),密码)

最终结果如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
base64UrlEncode(JWT)+"."+base64UrlEncode(有效载荷)+"."+HMACSHA256(base64UrlEncode(JWT) + "." + base64UrlEncode(有效载荷),密码)
三、JWT 注意事项

在使用 JWT 时需要注意以下事项:

  1. JWT 默认不加密,如果要写入敏感信息必须加密,可以用生成的原始令牌再次对内容进行加密;
  2. JWT 无法使服务器保存会话状态,当令牌生成后在有效期内无法取消也不能更改;
  3. JWT 包含认证信息,如果泄露了,任何人都可以获得令牌所有的权限;因此 JWT 有效期不能太长,对于重要操作每次请求都必须进行身份验证。
四、JWT 例子
  1. 自定义 JWT
  • 定义 JWT 头
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
string jwtHeader = "{\"alg\":\"HS256\",\"typ\":\"JWT\"}";
  • 定义有效载荷
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
string exp = GetTimeStamp(DateTime.Now.AddHours(1));
string jwtHeader = "{\"name\":\"zhangsan\",\"exp\":\"" + exp + "\",\"jti\":\"123123\"}";
  • 加密 JWT 头和有效载荷
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
string jwtHeaderBase64Url = Base64Url(jwtHeader);
string jwtPlayloadBase64Url = Base64Url(jwtPlayload);
  • 生成哈希签名
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
string signature = HMACSHA256(jwtHeaderBase64Url + "." + jwtPlayloadBase64Url,"123123");
  • 按顺序链接三部分,最终形成jwt
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
string jwtStr = jwtHeaderBase64Url + "." + jwtPlayloadBase64Url + "." + signature;

完整代码如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
static void Main(string[] args)
{
    string jwtHeader = "{\"alg\":\"HS256\",\"typ\":\"JWT\"}";
    string exp = GetTimeStamp(DateTime.Now.AddHours(1));
    string jwtPlayload = "{\"name\":\"zhangsan\",\"exp\":\"" + exp + "\",\"jti\":\"123123\"}";
    string jwtHeaderBase64Url = Base64Url(jwtHeader);
    string jwtPlayloadBase64Url = Base64Url(jwtPlayload);
    string signature = HMACSHA256(jwtHeaderBase64Url + "." + jwtPlayloadBase64Url,"123123");
    string jwtStr = jwtHeaderBase64Url + "." + jwtPlayloadBase64Url + "." + signature;
    Console.WriteLine(jwtStr);
    Console.ReadLine();
}

private static string HMACSHA256(string message, string key)
{
    var encoding = new System.Text.UTF8Encoding();
    byte[] keyByte = encoding.GetBytes(key);
    byte[] messageBytes = encoding.GetBytes(message);
    using (var hmacSHA256 = new HMACSHA256(keyByte))
    {
        byte[] hashMessage = hmacSHA256.ComputeHash(messageBytes);
        return BitConverter.ToString(hashMessage).Replace("-", "").ToLower();
    }
}
private static string Base64Url(string str)
{
    byte[] encodedBytes = Encoding.UTF8.GetBytes(str);
    string base64EncodedText = Convert.ToBase64String(encodedBytes);
    base64EncodedText = base64EncodedText
        .Replace("=", String.Empty)
        .Replace('+', '-')
        .Replace('/', '_');
    return base64EncodedText;
}

private static string GetTimeStamp(DateTime dt)
{
    DateTime startTime = TimeZone.CurrentTimeZone.ToLocalTime(new System.DateTime(1970, 1, 1, 0, 0, 0, 0));
    DateTime nowTime = dt;
    long unixTime =
        (long)System.Math.Round((nowTime - startTime).TotalMilliseconds, MidpointRounding.AwayFromZero);
    return unixTime.ToString();
}

运行结果如下:

2. 使用 .NET JWT 包 上面的代码我们在造轮子,但是 NuGet 中已经有造好的轮子了。在 NuGet 中搜索 jwt 并安装。使用 jwt 包我们只需要自定义有效载荷和密码即可,可生成三段格式的字符串 jwt 生成代码如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
static void Main(string[] args)
{
    string exp = GetTimeStamp(DateTime.Now.AddHours(1));
    var payload = new Dictionary<string, object>
    {
        {"name", "zhangsan"},
        {"exp", exp},
        {"jti", "123123"}
    };
    IJwtAlgorithm algorithm = new HMACSHA256Algorithm();
    IJsonSerializer serializer = new JsonNetSerializer();
    IBase64UrlEncoder urlEncoder = new JwtBase64UrlEncoder();
    IJwtEncoder encoder = new JwtEncoder(algorithm, serializer, urlEncoder);
    string jwtStr= encoder.Encode(payload, "123123");
    Console.WriteLine(jwtStr);
    Console.ReadLine();
}

同样,我们可以利用 jwt 包对生成的 jwt 进行解密,代码如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
IDateTimeProvider provider = new UtcDateTimeProvider();
IJwtValidator validator = new JwtValidator(serializer, provider);
IJsonSerializer serializer = new JsonNetSerializer();
IBase64UrlEncoder urlEncoder = new JwtBase64UrlEncoder();
IJwtDecoder decoder = new JwtDecoder(serializer, validator, urlEncoder);

var json = decoder.Decode(jwtStr, "123123", verify: true);

上述代码在项目中可以直接拿来用,只需修改其中的有效载荷和密码。

五、总结

本篇首先讲解了 jwt 的相关知识,然后通过自定义的方式和调用 jwt 包的方式手动创建了 jwt 。文章所讲的内容大家一定要切记,这些知识在开发中至关重要,在最后再补充两个小知识:

  1. 客户端发送 jwt 发送给服务器时,最好把 jwt 放在HTTP请求的Header Authorization,格式是:Authorization: Bearer jwt。
  2. jwt 不仅仅可以实现身份认证还可以在跨域 post 请求时将请求参数加入到有效载荷中,实现 post 跨域请求。 知识在开发中至关重要,在最后再补充两个小知识:
  3. 客户端发送 jwt 发送给服务器时,最好把 jwt 放在HTTP请求的Header Authorization,格式是:Authorization: Bearer jwt。
  4. jwt 不仅仅可以实现身份认证还可以在跨域 post 请求时将请求参数加入到有效载荷中,实现 post 跨域请求。
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2019/09/24 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
​一起重新全面认识JWT-Json Web Token
在这里,我整理了一下网上资源。在文章最后,有一个使用Java实现JWT生成和验证的完整案例。
谙忆
2021/02/20
1.2K0
​一起重新全面认识JWT-Json Web Token
JWT
上述模式在单机状态下没什么问题,但是如果是在服务器集群或者跨域的情况下,就没什么优势了。
仇诺伊
2020/04/23
1K0
JWT
JWT原理详解_电磁感应现象原理
发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/125153.html原文链接:https://javaforall.cn
全栈程序员站长
2022/08/02
5270
JWT原理详解_电磁感应现象原理
JWT令牌相关面试试题(举例说明)
JWT(JSON Web Token)是一种开放标准(RFC 7519),用于在各方之间以json数据格式安全的传输信息。
changwoo
2024/06/23
4560
JWT令牌相关面试试题(举例说明)
使用 JWT 实现 Token 验证
在开发过程中要实现登录,授权的基础功能有很多方法,通过 JWT 来实现非常方便,安全。因为是无状态的,比较于cookie 方式的实现,JWT能很好的解决跨域请求的问题。
张云飞Vir
2020/03/26
3.3K0
SpringBoot2.x+Shiro+JWT整合实现token认证(上)
正文开始前,先说一个自己的面试时被问的一个问题:说一下session+cookie认证和token认证的区别?
有来技术
2023/04/28
1.2K0
SpringBoot2.x+Shiro+JWT整合实现token认证(上)
【JWT】入门 *JWT*,并封装一个实用的 *JWT* 工具类
JSON Web 令牌 (JWT) 是一种开放标准 (RFC 7519),它定义了一种紧凑且独立的方式,用于将信息作为 JSON 对象在各方之间安全地传输 。此信息可以被验证和信任,因为它是经过数字签名的。JWT 可以使用密钥(使用 HMAC 算法)或使用 RSA 或 ECDSA 的公钥/私钥对进行签名。
.29.
2024/03/21
1.5K0
【JWT】入门 *JWT*,并封装一个实用的 *JWT* 工具类
FastAPI从入门到实战(8)——一文弄懂Cookie、Session、Token与JWT
HTTP 是无状态的。也就是说,HTTP 请求方和响应方间无法维护状态,都是一次性的,它不知道前后的请求都发生了什么。但有的场景下,我们需要维护状态。最典型的,一个用户登陆微博,发布、关注、评论,都应是在登录后的用户状态下的。这种情况下,各种鉴权就应运而生了。
MinChess
2022/12/27
5.1K0
FastAPI从入门到实战(8)——一文弄懂Cookie、Session、Token与JWT
PHP JWT简易使用
今天突然就想用一下jwt生成一下token,那么说干就干 首先我先下载了一下composer composer.phar 下载到本地以后,通过cmd命令行进行下载php-jwt,命令为:
超级小可爱
2023/02/20
1.7K0
代码审计 | JWT Token
JSON Web Token 缩写成 JWT,被用于和服务器的认证场景中,这一点有点类似于 Cookie 里的 Session id,关于这两者的区别可以看本文尾部的参考链接。
TeamsSix
2022/09/20
5270
代码审计 | JWT Token
JWT JSON Web Token的介绍
这种模式的问题在于,扩展性(scaling)不好。单机当然没有问题,如果是服务器集群,或者是跨域的服务导向架构,就要求 session 数据共享,每台服务器都能够读取 session。
javascript.shop
2019/09/04
5790
JWT JSON Web Token的介绍
JWT单点登录(源码学习)
由两部分组成,令牌类型(即:JWT)、散列算法(HMAC、RSASSA、RSASSA-PSS等)
全栈程序员站长
2022/08/31
5220
JWT单点登录(源码学习)
JWT简介
JSON Web Token(JWT)是目前最流行的跨域身份验证解决方案。微服务常见的认证方案
一觉睡到小时候
2019/12/25
5570
php 后端实现JWT认证方法示例
JWT是json web token缩写。它将用户信息加密到token里,服务器不保存任何用户信息。服务器通过使用保存的密钥验证token的正确性,只要正确即通过验证。基于token的身份验证可以替代传统的cookie+session身份验证方法。
用户2323866
2021/07/13
1.4K0
读懂JWT的使用,你就会用PHP如何实现了
什么是JWT JWT(json web token)是为了在网络应用环境间传递声明而执行的一种基于JSON的开放标准。 JWT的声明一般被用来在身份提供者和服务提供者间传递被认证的用户身份信息,以便于从资源服务器获取资源。比如用在用户登录上。
友儿
2022/09/11
1.1K0
SpringBoot整合JWT认证机制实现接口鉴权
session登录的认证方案是看,用户从客户端传递用户名和密码登录信息,服务端认证后将信息储存在session中,将session_id放入cookie中,以后访问其他页面,服务器都会带着cookie,服务端会自动从cookie中获取session_id,在从session中获取认证信息。
泰坦HW
2020/07/22
3.7K0
SpringBoot整合JWT认证机制实现接口鉴权
使用 NodeJS 实现 JWT 原理
我们用nodejs为前端或者其他服务提供resful接口时,http协议他是一个无状态的协议,有时候我们需要根据这个请求的上下获取具体的用户是否有权限,针对用户的上下文进行操作。所以出现了cookies session还有jwt这几种技术的出现, 都是对HTTP协议的一个补充。使得我们可以用HTTP协议+状态管理构建一个的面向用户的WEB应用。
前端老王
2020/09/23
1.3K0
使用 NodeJS 实现 JWT 原理
JWT 访问令牌
注意:该字符串只有jwt头部分不能被解析(通过加密的方式) 其他的两个部分 都可以(只通过Base64 URL编码 并没有被加密)
用户7630333
2023/12/07
5550
JWT 访问令牌
深入浅出JWT(JSON Web Token )
JSON Web Token(JWT)是一个开放式标准(RFC 7519),它定义了一种紧凑(Compact)且自包含(Self-contained)的方式,用于在各方之间以JSON对象安全传输信息。 这些信息可以通过数字签名进行验证和信任。 可以使用秘密(使用HMAC算法)或使用RSA的公钥/私钥对对JWT进行签名。
mantou
2018/05/05
4.2K5
深入浅出JWT(JSON Web Token )
JWT认证
JSON Web Token(JWT)是一个开放标准(RFC 7519),它定义了一种紧凑且自包含的方式,用于在各方之间以JSON方式安全地传输信息。由于此信息是经过数字签名的,因此可以被验证和信任。可以使用秘密(使用HMAC算法)或使用RSA或ECDSA的公钥/私钥对对JWT进行签名。
友儿
2022/09/11
8220
相关推荐
​一起重新全面认识JWT-Json Web Token
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档