JWT 简介与 C# 示例
〇、什么是 JWT ?
JWT,即 JSON Web Token,是一种基于 JSON 的开放标准(RFC 7519),主要用于在网络应用环境间安全地传递声明。这种声明被进行了数字签名,可以验证和信任,因此,它适用于各种需要信息安全性和无状态的应用。
在具体加密过程中,客户端会使用 RSA 算法生成 JWT 串,这里用到了私钥“加密”,而公钥是公开的,任何人都能解密,但内容无法变更。也就是说,在 JWT 中并没有纯粹的加密过程,而是通过加密保障了信息的完整性和真实性。
适用场景:
- 用户认证:当用户成功登录后,服务器会生成一个 JWT 令牌并返回给客户端,此后客户端只需携带这个令牌即可访问服务器提供的资源。
- 一次性验证:比如,用户注册后发一封邮件让其激活账户,通常邮件中需要有一个链接,这个链接需要具备能够标识用户、具有时效性、不能被篡改以及一次性的特性。这种场景就适合使用 JWT。
- 防止传输数据篡改:即使数据在传输过程中被截获,由于 JWT 可以使用加密算法对传输内容进行签名,因此很难同时篡改签名和传输内容。
优点:
- 更少的数据库连接:因其基于算法来实现身份认证,在使用 JWT 时查询数据的次数更少,可以获得更快的系统响应时间。
- 构建更简单:如果你的应用程序本身是无状态的,那么选择 JWT 可以加快系统构建过程。
- 跨服务调用:可以通过构建一个认证中心,来处理用户身份认证和发放签名的工作,其他应用服务在后续的用户请求中,可使用自有的公钥对用户签名进行验证。
- 无状态:你不需要向传统的 Web 应用那样将用户状态保存于 Session 中。
局限性:
- 安全性:由于 JWT 的 Payload 中负载信息,是使用 base64Url 编码的,并没有加密,因此 JWT 中不能存储敏感数据。
- 一次性:无状态是 JWT 的特点,但也导致了 JWT 是一次性的。想修改里面的内容,就必须签发一个新的 JWT。
- 严重依赖于秘钥:JWT 的生成与解析过程都需要依赖于秘钥(Secret),且都以硬编码的方式存在于系统中或配置里。如果秘钥泄露,系统的安全性将受到严重威胁。
- 服务端无法管理客户端的信息:如果用户身份发生异常(信息泄露或者被攻击),服务端很难将异常用户进行隔离。
- 服务端无法主动推送消息:服务端由于是无状态的,就无法推送消息到客户端。例如过期时间将至,服务端无法主动为用户续约,需要客户端向服务端发起续约请求。
- 冗余的数据开销:一个 JWT 签名的大小要远比一个 Session ID 长很多,如果你对有效载荷(payload)中的数据不做有效控制,其长度会成几何倍数增长,且在每一次请求时都需要负担额外的网络开销。
一、JWT 的组成
下边是一个示例密文 token:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1bmlxdWVfbmFtZSI6IuW8oOS4iSIsImVtYWlsIjoiemhhbmdzYW5AZXhhbXBsZS5jb20iLCJ0ZW1wa2V5IjoidGVtcHZhbHVl5YC8IiwibmJmIjoxNzAyODg2MjgxLCJleHAiOjE3MDI4ODYyOTEsImlhdCI6MTcwMjg4NjI4MX0.2nuyYrAxVq3aAReN257eMHKGG44j5QyPMabxMnSzVBU
密文起始就是,看起来是非常复杂,实际上有章可循的,如下图,密文以其中的两个句点为分隔,可分为三个部分:Header、Payload、Signature。

1.1 Header 头信息
Header 的主要作用是用来标识。通常是两部分组成:
- typ:type 的简写,令牌类型,也就是 JWT。
- alg:Algorithm 的简写,加密签名算法。
alg 参数 JWT 官网提供了 12 种算法,如下图,但一般都采用 HS256。

明文示例:
{
"alg": "HS256",
"typ": "JWT"
}
经过 Base64Url 编码后,就是密文中第一部分的内容:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9
1.2 Payload 有效负载
Payload 是 JWT 密文中的重要组成部分,也可称为 JWT claims,它包含了需要传递的数据信息,解密后的数据格式也是 Json。
claims 可以分为三种类型:registered(预定义声明)、public(公共声明)、private(私有声明)。
registered(预定义声明):不是强制性的,但推荐使用,以提供一组有用的、可互操作的声明。
其中主要包括四个:iss(issuer,发送数据人,标识发送 JWT 主体)、exp(expiration time,数据消息的过期时间,一般采用时间戳格式)、sub(subject,数据消息主题)、aud(audience,数据消息的接收者)。
public(公共声明):公共的声明可以添加任何的信息,一般添加用户的相关信息或其他业务需要的必要信息。一般不建议添加敏感信息,因为该部分在任何客户端均可解密。
private(私有声明):私有声明是提供者和消费者所共同定义的声明。
注:claims 声明名称一般只有三个字符长,因为 JWT 的目的是精简。
示例:
{
"unique_name": "张三",
"email": "zhangsan@example.com",
"tempkey": "tempvalue值"
}
经过 Base64Url 加密后,得到密文的第二部分内容:
eyJ1bmlxdWVfbmFtZSI6IuW8oOS4iSIsImVtYWlsIjoiemhhbmdzYW5AZXhhbXBsZS5jb20iLCJ0ZW1wa2V5IjoidGVtcHZhbHVl5YC8IiwibmJmIjoxNzAyODg2MjgxLCJleHAiOjE3MDI4ODYyOTEsImlhdCI6MTcwMjg4NjI4MX0
1.3 signature 签名信息
Signature 部分是对 Header 和 Payload 两部分的签名,作用是防止 JWT 被篡改。
要创建签名部分,前提是必须获取编码后的 Header、编码后的有效负载 Payload、secret 密钥、标头中 alg 指定的算法,一般为 HS256,然后才能对其进行签名。
HMACSHA256(
base64UrlEncode(header) + "." + base64UrlEncode(payload),
secret
)
加密后得到的密文就是 Token 中最后一部分内容。
密钥 secret 是保存在服务端的,服务端会根据这个密钥进行生成 token 和验证,所以需要严格保密。
二、JWT 身份验证的流程简介
JWT 经常用于身份验证流程,以下是一个简单的步骤:
- 用户首次登录,输入账号密码,请求登录接口 /users/login。
- 服务端验证登陆信息,并通过密钥创建 JWT 凭证。
- 服务端返回 JWT 凭证到浏览器,浏览器进行缓存。
- 用户操作触发请求,浏览器会自动将 JWT 凭证加入到请求的 Header 中。
- 服务端接收到请求,先判断 JWT 凭证的有效性。
- 若 JWT 凭证有效,则正常返回的请求结果数据;若校验不通过,则提示用户重新进行身份验证。

另外,在日常业务中,有可能出现并发异常问题。
当服务端在检查到请求的令牌过期之后,会提示用户再次做登录操作。
这在流程上没什么问题,但在页面加载后,如果同一个页面中有多个异步请求同时触发,每一个请求都携带原始令牌,在这样的设计下,就有可能出现在第一个请求到达后刷新了 Token,并更改了缓存中数据的时间戳,以至于剩余请求校验时发现时间戳不一致导致验证失败。
同一时间触发的请求越多,抛出的异常也就越多。虽然第一个请求已经刷新了 Token,但是其余的请求是失败的,页面中的数据并不完整,显然这是不正常的。那如何避免呐?
redis 锁机制:在触发更新 Token 时,将同一用户信息加锁,使得此用户的其他请求均失败,待登录验证通过后再重新加载。
Token 定时刷新:当用户在线时,间隔一段时间刷新一次 Token。要刷新令牌,API 需要一个新的端点,它接收一个有效的,没有过期的 JWT,并返回与新的到期字段相同的签名的 JWT。若用户长时间没登录,则直接跳转到登录页。
三、C# 简单实现
直接看代码吧。
// 测试一下
class Program
{
static void Main(string[] args)
{
JwtTest jwtTest= new JwtTest();
string key = "keayvkkakeyvaluyeaeayvalalujeehayvalguaealrue";
var claims = new[]
{
new Claim(ClaimTypes.Name, "张三"),
new Claim(ClaimTypes.Email, "zhangsan@example.com"),
new Claim("tempkey", "tempvalue值"),
};
string token = jwtTest.JwtEncode(key, claims);
Console.WriteLine(token);
// eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1bmlxdWVfbmFtZSI6IuW8oOS4iSIsImVtYWlsIjoiemhhbmdzYW5AZXhhbXBsZS5jb20iLCJ0ZW1wa2V5IjoidGVtcHZhbHVl5YC8IiwibmJmIjoxNzAzNTkxMTk4LCJleHAiOjE3MDM1OTEyMDgsImlhdCI6MTcwMzU5MTE5OH0.65Mx_ldbQijHevkalutHMaejQ06vhe5fW6e6-t-aziw
string json = jwtTest.JwtDecode(token, key);
// {"unique_name":"张三","email":"zhangsan@example.com","tempkey":"tempvalue值","nbf":1703591258,"exp":1703591268,"iat":1703591258}
Console.WriteLine(json);
}
}
验证一下:https://jwt.io/。

// JWT 加密解密类
public class JwtTest
{
public string JwtEncode(string keyvalue, Claim[] claims)
{
var key = Encoding.UTF8.GetBytes(keyvalue);
var tokenHandler = new JwtSecurityTokenHandler();
var tokenDescriptor = new SecurityTokenDescriptor
{
Subject = new ClaimsIdentity(claims),
Expires = DateTime.UtcNow.AddSeconds(10),
SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha256Signature)
};
var token = tokenHandler.CreateToken(tokenDescriptor);
var tokenString = tokenHandler.WriteToken(token);
Console.WriteLine($"加密后的JWT: {tokenString}");
return tokenString;
}
public string JwtDecode(string jwttoken, string publickey)
{
try
{
IJwtAlgorithm algorithm = new HMACSHA256Algorithm();
IJsonSerializer serializer = new JsonNetSerializer();
IDateTimeProvider provider = new UtcDateTimeProvider();
IJwtValidator validator = new JwtValidator(serializer, provider);
IBase64UrlEncoder urlEncoder = new JwtBase64UrlEncoder();
IJwtDecoder decoder = new JwtDecoder(serializer, validator, urlEncoder, algorithm);
var json = decoder.Decode(jwttoken, publickey, verify: true);
return json;
}
catch(Exception ex)
{
return "";
}
}
}
参考:https://jwt.io/introduction https://juejin.cn/post/7232550589964140602 https://cloud.tencent.com/developer/article/2148676
JWT 简介与 C# 示例的更多相关文章
- PCRE函数简介和使用示例【转】
PCRE函数简介和使用示例 标签: 正则表达式listbuffercompilationnullperl 原文地址:http://blog.csdn.net/sulliy/article/detail ...
- Python Sklearn.metrics 简介及应用示例
Python Sklearn.metrics 简介及应用示例 利用Python进行各种机器学习算法的实现时,经常会用到sklearn(scikit-learn)这个模块/库. 无论利用机器学习算法进行 ...
- 第九节:JWT简介和以JS+WebApi为例基于JWT的安全校验
一. 简介 1. 背景 传统的基于Session的校验存在诸多问题,比如:Session过期.服务器开销过大.不能分布式部署.不适合前后端分离的项目. 传统的基于Token的校验需要存储Key-Val ...
- Okhttp【简介】应用 示例
资源 GitHub:https://github.com/square/okhttp 官网 文档 API You'll also need Okio[https://github.c ...
- JSON Web Token (JWT) 简介
JSON Web Token (JWT) 是一种基于 token 的认证方案. JSON Web Token 的结构 一个 JWT token 看起来是这样的: eyJhbGciOiJIUzI1NiI ...
- JWT 简介
JWT是一种用于双方之间传递安全信息的简洁的.URL安全的表述性声明规范.JWT作为一个开放的标准(RFC 7519),定义了一种简洁的,自包含的方法用于通信双方之间以Json对象的形式安全的传递信息 ...
- 使用XStream是实现XML与Java对象的转换(1)--简介及入门示例
一.简单介绍 XStream是thoughtworks开发的开源框架,用于实现XML数据于Java对象.Json数据的转换.它不需要schema或其他的mapping文件就可以进行java对象和xml ...
- 使用 JWT 生成 Token 代码示例
JSON Web Token,简称 JWT, 是一个开放的标准(RFC 7519),它定义了以一种紧凑的.自包含的 JSON 对象在各方之间安全传输信息的方式.该信息含有数字签名,可以被验证和信任. ...
- JWT简介
JSON Web Token(缩写 JWT)是目前最流行的跨域认证解决方案,本文介绍它的原理和用法. 一.跨域认证的问题 互联网服务离不开用户认证.一般流程是下面这样. 1.用户向服务器发送用户名和密 ...
- Ice简介+Qt代码示例
1.ICE是什么? ICE是ZEROC的开源通信协议产品,它的全称是:The Internet Communications Engine,翻译为中文是互联网通信引擎,是一个面向对象的中间件,它封装并 ...
随机推荐
- 一篇文章让你弄懂分布式一致性协议Paxos
一.Paxos协议简介 Paxos算法由Leslie Lamport在1990年提出,它是少数在工程实践中被证实的强一致性.高可用.去中心的分布式协议.Paxos协议用于在多个副本之间在有限时间内对某 ...
- 618京东到家APP-门详页反爬实战
一.背景与系统安全需求分析 1. 系统的重要性 上图所示是接口所属位置.对电商平台或在线商店而言,分类查商品都是很重要的,通过为用户提供清晰的商品分类,帮助他们快速找到所需产品,节省浏览时间,提升购物 ...
- JDK17和JDK8在windows上同时安装方便切换
参考:https://blog.csdn.net/chencaw/article/details/121674479 一.JDK8的安装 1.电脑上已经安装了JDK8,安装主要步骤如下 (1)创建JA ...
- VOLTE:MIUI14无5G信号、通话质量差、短信收不到的原因之一
在最近一次miui版本更新后的一段时间里,先后出现以下一些情况: 1. 在"双卡与移动网络"设置中,无论如何折腾"5G网络"开关或者"5G网络模式选择 ...
- Linux服务器使用Redis作为数据缓存,并用log4j2进行日志记录
前言 个人网站使用Vue作为前端,SpringBoot作为后端,MySQL作为数据库,但前端每次请求都会从MySQL数据库中读取数据,而MySQL数据库的数据是存储于服务器磁盘中,所以响应速度有一定影 ...
- mpi转以太网连接300PLC在气动系统中的应用
mpi转以太网连接300PLC在气动系统中的应用 某企业装备有限公司 摘要 工业通讯迅速发展的今天,MPI转以太网通讯已经发展为成熟,稳定,高效通讯 方式,兴达易控自主研发的MPI转以太网模块MPI- ...
- firewalld规则配置
firewalld规则配置 一.概念 动态防火墙 启动新规则时,不会像iptables一样,先清空规则,再启动所有规则,如此会对现在程序有影响,哪怕只是一条规则.而firewalld 规则变更不需要对 ...
- 9.1 运用API创建多线程
在Windows平台下创建多线程有两种方式,读者可以使用CreateThread函数,或者使用beginthreadex函数均可,两者虽然都可以用于创建多线程环境,但还是存在一些差异的,首先Creat ...
- 前端脚手架CLI生成模版命令工具(包括,npm包的发布,脚手架的搭建,注意事项,优化等)
写在前面 这是停更以后,续更的一篇文章. 为什么好长时间都没有更新,因为去其他平台更新了,包括掘金,思否,简书等. 在那些地方感觉没有归属感,有的平台原创审核很麻烦,简书号称可以获得打赏,可是码了几十 ...
- 使用ResponseSelector实现校园招聘FAQ机器人
本文主要介绍使用ResponseSelector实现校园招聘FAQ机器人,回答面试流程和面试结果查询的FAQ问题.FAQ机器人功能分为业务无关的功能和业务相关的功能2类. 一.data/nlu.y ...