JWT权限验证

在Web开发中,用户认证授权是确保系统安全和数据安全的关键环节。随着前后端分离、微服务架构等技术的普及,传统的基于session的用户认证机制已经很难去满足现代Web应用的需求。JWT(JSON Web Tokens)作为一种轻量级的认证和授权机制,在Web开发中得到了广泛的应用。本文将详细介绍JWT的基本原理、核心知识点以及在实际项目中的应用。

什么是JWT

JWT,全称JSON Web Tokens,是一种开放标准(RFC 7519)定义的方式,用于在双方之间安全地传输信息。这些信息可以包括用户的身份信息、角色、权限等。JWT通过编码、签名等方式保证传输的信息的安全性和可验证性。JWT不是一种只能做权限验证的工具,而是一种标准化的数据传输规范,所以只要是在系统之间进行简短而又需要一定安全保护的数据传输都可以使用JWT规范来传输。而规范是不受平台限制的,所以JWT是可以跨平台使用的。

JWT结构

JWT 通常由三部分组成,它们通过点(.)分隔,分别是:Header(头部)、Payload(负载)和 Signature(签名)。

1. Header(头部)

Header 通常包含两部分信息:

  • typ(类型):这是一个描述 JWT 的类型的字符串。对于 JWT,它通常被设置为 JWT
  • alg(算法):这是用于签名 JWT 的算法的名称。例如,它可以是 HMAC SHA256 或 RSA。

Header 部分会被 Base64Url 编码以形成 JWT 的第一部分。

一个 Header 对象可能是这样的:

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

而经过Base64Url 编码后,它可能看起来像这样 

eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9

2. Payload(负载)

Payload 包含有关用户或其他声明的信息。声明分为三种类型:注册的声明(Registered claims)、公共的声明(Public claims)和私有的声明(Private claims)。

  • 注册的声明:这是一组先定义好的声明,它们不是强制性的,但是推荐使用,用来提供一组有用的、可以互操作的声明。例如:iss(发行人)、exp(过期时间)、sub(主题)等。
  • 公共的声明:这些声明可以与和JWT 的接收方共享。
  • 私有的声明:这些是提供者和消费者之间定义的自定义声明。

Payload 也会被 Base64Url 编码以形成 JWT 的第二部分。

一个 Payload 对象可能是这样的:

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

Base64Url 编码后,它可能看起来像这样:

eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9

3. Signature(签名)

为了获得签名部分,我们先要对 Header 和 Payload 进行 Base64Url 编码,然后用点(.)把它们给连在一起。然后再去用指定的算法和密钥对连接后的字符串进行哈希。哈希的结果作为 JWT 的第三部分。

完整的 JWT 是三部分的连接,看起来像这样:

eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c

 Claim的概念

什么是Claim

在JWT中,Claim(生称)的用途主要是存储和传递用户身份信息和其他相关数据。在JWT中,Claim被编码后存储在JWT的Payload部分。当JWT被接收方接收时,接收方可以解码JWT并读取其中的Claim,从而获取用户信息和其他相关数据。

Claim就像是我们小时候玩的“传话游戏”中的每一句话。想象一下,你是那个起始的玩家,想要告诉队伍最后面的小朋友一个秘密,这个秘密就是JWT中的信息,而每个小朋友传递的一句话就是JWT中的一个Claim。

简单来说,Claim就是JWT中用来存储用户身份信息和其他相关数据的部分。这些数据可以是用户的名字、角色、权限,甚至是用户设备的信息等。这些数据被编码后,就形成了JWT中的一个个Claim。

Claim的类型和用途

Claim的类型多种多样,但大致可以分为如下几类:

1. 注册声明(Registered Claims)

这些是JWT标准定义的声明,它们不是强制性的,但我们推荐使用。比如:

  • iss (Issuer):发行人,一般是创建JWT的服务器。
  • sub (Subject):主题,通常是一个用户账号的唯一标识。
  • exp (Expiration Time):过期时间,表示JWT在什么时间之后不再有效。
  • aud (Audience):受众,表示JWT是为哪个受众创建的,通常是接收JWT的一方。

2. 公共声明(Public Claims)

公共声明是用户定义的声明,这些声明可以与JWT的接收方共享,但不需要在JWT标准中注册。比如,你可以在JWT中添加一个名为username的声明来存储用户的名字。这些声明可以用来存储一些额外的信息。

3. 私有声明(Private Claims)

私有声明是提供者和消费者之间定义的自定义声明。这些声明既不是注册的也不是公共的,而是仅在特定的应用或组织内部使用。比如,你的应用可能有一个名为employeeId的私有声明,用来存储员工的唯一ID。

权限验证的基本流程

1)客户端向授权服务系统发起请求,申请获取“令牌”(Token)。
2)授权服务根据用户身份,生成一张专属的JWT令牌,并返回给客户端。
3)客户端在后续请求中将JWT令牌放置在HTTP请求的headers中,发送给主服务系统。主服务系统从headers中获取JWT令牌,验证其有效性,并解析出用户的身份和权限信息,然后基于这些信息做出相应的处理(如允许或拒绝访问资源)。

JWT的好处

服务端无状态

JWT通过客户端存储的token来实现服务端无状态。当用户成功登录后,服务器会生成一个包含用户信息的JWT,并将这个JWT返回给客户端。客户端会将JWT存储在本地(比如浏览器的localStorage或cookie中),并在后续的请求中带上这个JWT。服务器在接收到请求后,会验证JWT的有效性,如果JWT有效,说明用户已经登录,并可以从JWT中获取用户信息。

“服务端无状态”指的是服务器不保存或追踪客户端的会话信息。在传统的web应用中,服务器通常会为每个客户端维护一个会话(session),这个会话中包含了用户的登录状态、权限等信息。然而,在JWT的体系下,服务器不再需要这么做。

解决跨域问题

由于JWT是存储在客户端的,它不受浏览器同源策略的限制。因此,即使在不同的源之间,只要客户端能够在请求中带上JWT,服务器就能够验证用户的身份。这使得JWT在处理跨域请求时更加灵活和方便。

系统解耦

JWT使得前后端系统更加解耦。前端不再需要依赖于后端的会话管理,可以更加独立地进行开发和部署。同时,由于JWT中包含了用户信息,前端可以在一定程度上减少对后端服务的依赖,提高系统的响应速度和可用性。

防止跨站点脚本攻击(XSS)

JWT本身不能直接防止XSS攻击,但它是存储在客户端的(通常是localStorage或cookie),我们可以采取一些措施来降低XSS攻击的风险:

  1. 设置HttpOnly属性:如果JWT存储在cookie中,可以设置HttpOnly属性,使得JavaScript无法访问该cookie,从而防止XSS攻击者通过JavaScript窃取JWT。
  2. 设置Secure属性:对于HTTPS网站,可以设置Secure属性,使得cookie只能通过HTTPS协议传输,增加了数据传输的安全性。
  3. 短有效期:设置较短的JWT有效期,即使JWT被窃取,攻击者也只有有限的时间来利用它。
  4. 使用HTTPS:确保整个通信过程都使用HTTPS,防止数据在传输过程中被窃取或篡改。

JWT的使用与实现

关于JWT授权,其实过程并不复杂。我们可以将其简化为四个步骤来理解:

  1. 生成JWT令牌:这就像是制作一张公司门禁卡,卡上包含了一些特定的信息(如员工的ID、部门等)。
  2. 定义授权机制:这就像规定哪些地方是领导办公室,哪些员工可以进出。
  3. 实现认证方案:在公司中,我们需要安装刷卡机来验证门禁卡的有效性。同样地,在Web应用中,我们需要一个机制来验证JWT令牌的真实性。
  4. 开启中间件服务:这就像是公司的安保部门,负责检查每一个进入公司的人是否持有有效的门禁卡。

接下来,我们将详细讨论如何生成JWT令牌。

生成JWT令牌

为了生成JWT令牌,我们可以使用JwtHelper这样的工具类。这个类通常包含了一个IssueJwt方法,用于根据给定的用户信息生成JWT字符串。

public static class JwtHelper  
{  /// <summary>  /// 颁发JWT字符串  /// </summary>  /// <param name="tokenModel">包含用户信息的TokenModelJwt对象</param>  /// <returns>生成的JWT字符串</returns>  public static string IssueJwt(TokenModelJwt tokenModel)  {  // 从配置文件中获取发行人(Issuer)和受众(Audience)  string iss = Appsettings.app(new string[] { "Audience", "Issuer" });  string aud = Appsettings.app(new string[] { "Audience", "Audience" });  // 从配置文件中获取密钥(Secret)  string secret = AppSecretConfig.Audience_Secret_String;  // 创建Claims列表  var claims = new List<Claim>  {  // 这里将用户的部分信息,比如 uid 存到了Claim 中  new Claim(JwtRegisteredClaimNames.Jti, tokenModel.Uid.ToString()), // JWT的唯一标识符  new Claim(JwtRegisteredClaimNames.Iat, $"{new DateTimeOffset(DateTime.Now).ToUnixTimeSeconds()}"), // JWT的签发时间  new Claim(JwtRegisteredClaimNames.Nbf, $"{new DateTimeOffset(DateTime.Now).ToUnixTimeSeconds()}"), // JWT的生效时间  // JWT的过期时间,这里设置为1000秒后过期  new Claim(JwtRegisteredClaimNames.Exp, $"{new DateTimeOffset(DateTime.Now.AddSeconds(1000)).ToUnixTimeSeconds()}"),  // (可选)添加额外的过期时间描述  new Claim(ClaimTypes.Expiration, DateTime.Now.AddSeconds(1000).ToString()),  new Claim(JwtRegisteredClaimNames.Iss, iss), // 发行人  new Claim(JwtRegisteredClaimNames.Aud, aud), // 受众  // ... 可以添加其他自定义的Claims,如用户角色等  claims.AddRange(tokenModel.Role.Split(',').Select(s = >new Claim};  // 使用JWT库(如System.IdentityModel.Tokens.Jwt)和密钥(secret)来生成JWT字符串  var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(secret));var creds = new SigningCredentials(key,SecurityAlgorithms,HmacSha256);var jwt = new JwtSecurityToken(issuer : iss,claims : claims,signingCredentilas: creds);var jwtHandler = new JwtSecurityTokenHandler();var encodedJwt = jwtHandler.WirteToken(jwt);return encodedJwt ;  }  
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/37675.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【数据分析】1、用Pandas计算数据相关性系数

相关性系数和相关分析是了解变量之间关系的重要工具。通过合理选择相关性系数和科学分析数据&#xff0c;能够有效揭示变量之间的关系&#xff0c;为进一步研究和决策提供有力支持。在实际应用中&#xff0c;应结合业务背景、数据特性和统计原则&#xff0c;谨慎解释和应用相关…

物联网相关

因为收藏夹上限了&#xff0c;所以只能这个帖子来记录物联网相关得文章了。 链接: 搭建自己的MQTT服务器、实现设备上云(WindowsEMQX) 链接: Windows系统下本地MQTT服务器搭建&#xff08;保姆级教程&#xff09;

【小学期】常用基于Swing的七个静态界面

示例1&#xff1a;基本的带按钮和标签的界面 import javax.swing.*; import java.awt.*;public class SimpleSwingApp1 {public static void main(String[] args) {JFrame frame new JFrame("Simple Swing App 1");frame.setDefaultCloseOperation(JFrame.EXIT_ON_C…

【linux】从零到入门

linux概述 Linux是一个免费使用和自由传播的一套操作系统。用户可以无偿地得到它地源代码&#xff0c;和大量地应用程序&#xff0c;并且可以随意修改和增加它们。 Linux的内核起初由林纳斯编写。内核是啥&#xff1f; 驱动设备&#xff0c;文件系统&#xff0c;进程管理&…

UE5(c++)demo开发日志(1):Actor类添加

工具---新建c类---选用Actor&#xff0c;创造出头文件(.h&#xff0c;用于声明变量、函数、重写父类函数等)和源文件(.cpp&#xff0c;涉及到具体功能实现)&#xff0c;客户端界面成功显示出来新建类&#xff1a; Actor头文件默认方法简介&#xff1a; UCLASS(): ue提供的宏&a…

算法-位运算基础

文章目录 1. 前置知识2. 交换两个数3. 比较两个数的大小3. leetcode268 寻找缺失的数字4. leetcode136 只出现一次的数字5. leetcode260 只出现一次的数字|||6. leetcode137 只出现一次的数字||7. 2/3的幂8. 大于等于该数字的最小2的幂9. leetcode201 数字范围按位与10. 位运算…

Docker部署Dillinger个人文本编辑器

Docker部署Dillinger个人文本编辑器 一、Dillinger介绍1.1 Dillinger简介1.2 Dillinger使用场景 二、本地环境介绍2.1 本地环境规划2.2 本次实践介绍 三、本地环境检查3.1 检查Docker服务状态3.2 检查Docker版本3.3 检查docker compose 版本 四、拉取Dillinger镜像五、部署Dill…

汇聚荣拼多多运营好吗?

在当前电商行业竞争激烈的背景下&#xff0c;拼多多凭借其独特的商业模式和市场定位迅速崛起&#xff0c;成为众多商家和品牌争相入驻的平台。对于“汇聚荣拼多多运营好吗?”这一问题&#xff0c;答案是肯定的。拼多多不仅提供了一个广阔的市场空间&#xff0c;还通过其创新的…

HTML5+JavaScript单词游戏

HTML5 JavaScript单词游戏 数据字典格式&#xff1a;每行一个 单词 &#xff0c;单词和解释用空格分隔&#xff0c;如 a art.一(个)&#xff1b;每一(个) ability n.能力&#xff1b;能耐&#xff0c;本领 able a.有能力的&#xff1b;出色的 baby n.婴儿&#xff1b;孩子…

数据库对比脚本,java如何对比两个数据库的表字段的不同

因为有时候开发环境和 测试环境&#xff0c;有时候会有不同的数据库表&#xff0c;比如有些加字段了&#xff0c;所以这个脚本就实现了对比两个数据库连接的数据库到底哪里不一样&#xff0c;输出到控制台 package com.junfun.pms;import lombok.extern.slf4j.Slf4j;import ja…

25届最近5年北京工业大学自动化考研院校分析

北京工业大学 目录 一、学校学院专业简介 二、考试科目指定教材 三、近5年考研分数情况 四、近5年招生录取情况 五、最新一年分数段图表 六、初试大纲复试大纲 七、学费&奖学金&就业方向 一、学校学院专业简介 二、考试科目指定教材 1、考试科目介绍 2、指定教…

C++进修——C++核心编程

内存分区模型 C程序在执行时&#xff0c;将内存大方向划分为4个区域 代码区&#xff1a;存放函数体的二进制编码&#xff0c;由操作系统进行管理全局区&#xff1a;存放全局变量和静态变量以及常量栈区&#xff1a;由编译器自动分配释放&#xff0c;存放函数的参数值&#xff…

grpc学习golang版( 三、proto文件数据类型 )

系列文章目录 第一章 grpc基本概念与安装 第二章 grpc入门示例 第三章 proto文件数据类型 第四章 多服务示例 第五章 多proto文件示例 第六章 服务器流式传输 第七章 客户端流式传输 第八章 双向流示例 文章目录 一、proto语法二、proto中的标量类型三、proto中的数组类型四、p…

资料导览(持续更新)

经典推荐 多模态大模型&#xff1a;基础架构 图解DSPy&#xff1a;Prompt的时代终结者&#xff1f;&#xff01; vLLM, LMDeploy, MLC-LLM, TensorRT-LLM, and TGI的性能小实验 优雅谈大模型13&#xff1a;一文读懂LoRA/DoRA/MoRA 新鲜速递&#xff1a;图解新颖LLM的CoPE位…

C#测试调用DotnetSpider爬取网页内容

微信公众号“DotNet”的文章《.NET快速实现网页数据抓取》介绍了调用开源网页爬取模块DotnetSpider爬取cnblog网站文章的基本方式。之前学习过使用HtmlAgilityPack抓取并分析网页内容&#xff0c;DotnetSpider也依赖HtmlAgilityPack模块&#xff0c;不过前者属于轻量、高效的爬…

C++ 运算符的优先级和结合性表

优先级和结合性表 优先级运算符描述结合性1::作用域解析运算符左到右2() [] . -> --后缀运算符左到右3 -- - ! ~ * & sizeof new delete typeid一元运算符右到左4* / %乘除取模左到右5 -加法和减法左到右6<< >>左移和右移左到右7< < > >关系…

大数据开发如何管理项目

在面试的时候总是 会问起项目&#xff0c;那在大数据开发的实际工作中&#xff0c;如何做好一个项目呢&#xff1f; 目录 1. 需求分析与项目规划1.1 需求收集与梳理1.2 可行性分析1.3 项目章程与计划 2. 数据准备与处理2.1 数据源接入2.2 数据仓库建设2.3 数据质量管理 3. 系统…

【微服务】Alibaba Cloud Linux环境下Docker以及MySQL安装

部署Docker 1.安装dnf dnf是新一代的rpm软件包管理器 yum -y install dnf2.安装社区版Docker&#xff08;docker-ce&#xff09; 添加docker-ce的dnf源 dnf config-manager --add-repohttps://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo安装Alibaba Cloud…

MySQL 12种锁:真实业务与流程图解析

文章目录 1. 表级锁&#xff08;Table Lock&#xff09;场景1&#xff1a;全表扫描统计 2. 行级锁&#xff08;Row Lock&#xff09;场景2&#xff1a;修改特定用户信息 3. 全局锁&#xff08;Global Lock&#xff09;场景3&#xff1a;数据备份 4. 意向锁&#xff08;Intent L…

高性能并行计算华为云实验三:蒙特卡罗算法实验

目录 一、实验目的 二、实验说明 三、实验过程 3.1 创建蒙特卡罗算法源码 3.2 Makefile的创建与编译 3.3 主机文件配置与运行监测​​​​​​​ 四、实验结果与分析 4.1 原教程对应的实验结果 4.2 改进后的实验结果 五、实验思考与总结 5.1 实验思考 5.2 实验总结…