百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术教程 > 正文

JWT授权认证详细解读

mhr18 2024-12-07 21:46 15 浏览 0 评论

授权机制,当我们说到这个问题的时候,大家对它的第一印象是在哪个地方呢?是不是曾经某培训机构教授的 SSO 单点登录的,是的没错,而这种 SSO 的单点登录在当年的培训机构中,使用的就是 Session 共享,也就是用 Redis 做中间模拟 Session ,但是授权机制真的有这么简单么?接下来阿粉就来强势对比一下关于授权机制了。

Cookie-Session 认证授权

Cookie-Session 认证机制就是为一次请求认证在服务端创建一个Session对象,同时在客户端的浏览器端创建了一个Cookie对象;通过客户端带上来Cookie对象来与服务器端的session对象匹配来实现状态管理的。

但是这时候我们就得考虑一下 Cookie 的存活时间了,当我们关闭浏览器的时候,Cookie就会被删除,就算我们调整了 Cookie 的存活时间,但是他依然有很大的弊端,Cookie 是很容易被拦截到的,阿粉之前就看到过某个知名的 OA 系统,就曾经把用户的ID 放到了 Cookie 中,只不过是把 Cookie 里面的键给设置成了 imageUrl,但是实际上这种,看着有点搞人的意思,图片地址是一堆长的字符串,你在前端拦截到之后, 明眼人一眼就能知道这种肯定不是图片路径,而且当我们使用 Cookie 进行用户识别,用户就会很容易受到跨站请求伪造的攻击,也就是我们经常说的 CSRF .

JWT

既然在这里对比 JWT ,我们就得先知道 JWT 是个什么东西,JSON Web Token (JWT) 实际上用大白话说,它就是一种认证机制,让后台知道请求是来自于受信的客户端。

技术都是随着问题出现的,只要有问题,那么很快就会有解决这个问题的技术出现,同样,JWT 出现的只不过比较早而已,因为现在微服务,分布式横行遍布,不管是大公司,还是小公司,很多都开始做分布式的项目,这做分布式也不仅仅是停留在了只存在大公司了,既然选择使用了分布式,那么各种各样的问题就来了。

  • 跨域身份验证
  • 分布式session共享
  • 分布式站点的单点登录

JWT 是个什么玩意

我们先看一下官方网站给的内容,What is JSON Web Token?

JSON Web Token (JWT) is an open standard (RFC 7519) that defines a compact and self-contained way for securely transmitting information between parties as a JSON object. This information can be verified and trusted because it is digitally signed. JWTs can be signed using a secret (with the HMAC algorithm) or a public/private key pair using RSA or ECDSA

JSON Web令牌(JWT)是一种开放标准(RFC7519),它定义了一种紧凑且独立的方式,用于在各方之间安全地作为JSON对象传输信息。由于该信息是数字签名的,因此可以验证和信任此信息。可以使用秘密(使用HMAC算法)或使用RSA或ECDSA的公钥/私钥对对对对JWTs进行签名.

阿粉就直接用百度翻译了,结果翻译出来竟然差不多,看来百度翻译有时候也没有那么差劲。

那么什么时候需要去使用 JWT 呢?

在官网中,给出了两种情况下去使用 JWT ,AuthorizationInformation Exchange,一种是授权,授权我们都懂,就是当用户登录后,每个后续请求都将包括JWT,允许用户访问该令牌允许的路由、服务和资源,而资源交换,实际上简单的说,就是在数据传输中用 JWT 令牌在安全地在各方之间传输信息

那么我们既然知道了什么时候来使用 JWT, 我们就来看看 JWT 到底是长成什么样子,

JWT 构成:

  • Header 头部
  • Payload 有效载荷
  • Signature 签名

我们从官网上获取了一段的内容,然后逐个来看,

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c

既然它说 JWT 是由三段信息构成的,而这三段信息,是用 .来进行隔开的,也就是上面这长串的字符串,

Header 头部,我们看到图里面也给出了,Header 中存储的实际上就是2部分的内容。typ:类型 alg:加密算法,

然后他是对头部进行的 Base64 加密,我就是我们在官网摘下来的第一段的内容,就出现了加密字符串 eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9

Payload 有效载荷

实际上有效载荷实际上就是存储有效信息的地方,那么他都存储了一些什么内容呢?

  • iss (issuer):签发人
  • exp (expiration time):过期时间
  • sub (subject):主题
  • aud (audience):受众
  • nbf (Not Before):生效时间
  • iat (Issued At):签发时间
  • jti (JWT ID):编号( jwt的唯一身份标识,主要用来作为一次性token,从而回避重放攻击)

为什么会有这么多,因为在 JWT 的规范中,他告诉我们的是,建议但不强制使用,也就是说,你可以根据自身的应用去选择使用,比如官网给出的,他就没有写全面,就使用了三个:

{
  "sub": "1234567890",
  "name": "John Doe",
  "iat": 1516239022
}

而实际上这部分的内容却是比较重要的内容。

signature签名信息

实际上这个就是一个组装起来的,将头部和载荷用’.'号连接,再加上一串密钥,经过头部声明的加密算法加密后得到签名。

这个 Header 和 Payload 都是加密过的,而在这个地方它还进行了 “加盐” 的操作,将这三部分用.连接成一个完整的字符串,构成了最终的jwt

jwt其实并不是什么高深莫测的技术,在很多技术人的眼中,可能觉得他会非常的low ,实际上虽然不高端,但是也没有那么 low,认证服务器通过对称或非对称的加密方式利用payload生成signature,并在header中申明签名方式,这就是 JWT 的本质实现方式。

JWT 的有点其实很明显,

  • 通过验证签名的方式可以直接在资源服务器本地完成授权校验
  • 在payload中可以包含用户相关信息,实现了token和用户信息的绑定

使用场景一般是用在一次性的身份验证上,千万不要想着去用 JWT 去代替 Session,虽然 JWT 可以设置失效时间,但是在有效期内,它是无法作废的。

OAuth2认证

OAuth 引入了一个授权层,用来分离两种不同的角色:客户端和资源所有者。资源所有者同意以后,资源服务器可以向客户端颁发令牌。客户端通过令牌,去请求数据。

其实这个 OAuth 的核心就是向第三方应用颁发令牌,而在 Oauth2 中定义了四种获得令牌的流程,也就是通俗的四种授权方式,但是我们经常使用的也就是那么一种。

  • 授权码
  • 隐藏式(简化)
  • 密码式
  • 客户端凭证

授权码模式

这是在 Oauth 里面的功能算是最完整的,而且流程最严密的授权模式。

授权码模式的步骤:

  • 1.用户访问客户端,后者将前者导向认证服务器
  • 2.用户选择是否给予客户端授权
  • 3.假设用户给予授权,认证服务器将用户导向客户端事先指定的"重定向URI"(redirection URI),同时附上一个授权码
  • 4.客户端收到授权码,附上早先的"重定向URI",向认证服务器申请令牌。这一步是在客户端的后台的服务器上完成的,对用户不可见
  • 5.认证服务器核对了授权码和重定向URI,确认无误后,向客户端发送访问令牌(access token)和更新令牌(refresh token)

其实授权码模式就相当于是第三方的应用去先申请一个授权码,然后再用该授权码获取令牌。

总结下来就是四个步骤 :

1:请求授权码

2:返回授权码

3:请求令牌

4:返回令牌

我们给出一个例子,然后分析一下。


https://2.com/oauth/authorize? //授权地址
  response_type=code& //参数1:response_type :这里表示授权的类型,此处的值固定为"code"
  client_id=CLIENT_ID& //参数2:client_id :表示客户端的ID
  redirect_uri=CALLBACK_URL& //参数3:redirect_uri :表示重定向URL
  scope=read //参数4:scope: 表示申请的权限范围
  

上面的地址,就相当于第一步,携带所需要的参数请求 网站2,请求获取授权码。

https://1.com/callback?code=AUTHORIZATION_CODE //code 授权码

上面的地址就是第二步了,网站2给网站1返回授权码,


https://2.com/oauth/token?
 client_id=CLIENT_ID&   客户端ID
 client_secret=CLIENT_SECRET& 客户端密钥
 grant_type=authorization_code& 使用的授权模式 authorization_code :授权码模式
 code=AUTHORIZATION_CODE& 授权码
 redirect_uri=CALLBACK_URL  表示重定向URL

上面的地址就到第三步了,用授权码去索要令牌的请求就发送了。

请求发送完成后,2网站收到请求之后,这时候就向 重定向URL 发送以下的 JSON 数据,

{    
  "access_token":"ACCESS_TOKEN", //访问令牌
  "token_type":"bearer",// 令牌类型
  "expires_in":2592000, // 过期时间
  "refresh_token":"REFRESH_TOKEN", // 更新令牌
  "scope":"read", // 权限范围 只读
  "uid":100101, //
  "info":{...} //
}

这时候 访问令牌 我们就要有了,这完成所有的步骤后,我们就拿到了我们访问的令牌了,也就是我们完成了所需要的授权了。

隐藏式

其实隐藏式就是简化版的授权模式,他省略了获取 授权码 的过程,而是直接请求获取 令牌 的过程。

案例如下:


https://2.com/oauth/authorize?
  response_type=token& 授权的类型,此处的值固定为"token"
  client_id=CLIENT_ID&  客户端ID
  redirect_uri=CALLBACK_URL& 表示重定向URL
  scope=read  权限范围 只读

上面授权类型直接就是索要令牌,

第二步也很简单,就是直接给你返回你需要的令牌

https://1.com/callback#token=ACCESS_TOKEN

上面的 Token 就是我们需要的令牌了,

密码式

这种为什么称之为 密码式 ,是因为它在请求的时候,是用密码去换令牌,这就需要一个前提,你对这个网站有高度的信用度,如果你不信用他,他给你账号密码作用都不大,给了你也不会授权给它 Token 不是么。

案例步骤如下:

1.请求令牌


https://oauth.2.com/token?
  grant_type=password& 授权方式:指定为密码式
  username=USERNAME&  用户名
  password=PASSWORD&  密码
  client_id=CLIENT_ID  客户端ID
  

2.返回令牌

https://1.com/callback#token=ACCESS_TOKEN

这个感觉和隐藏式差距不大,一个是直接要,一个是拿着参数要。

凭证式

这个凭证式的步骤也是比较少的,实际上阿粉感觉这种方式不知道算不算是授权的方式,因为这种模式是客户端以自己的名义向"授权服务提供者"进行认证,但是既然说是,那就暂且的认定他是,

1:请求令牌

https://oauth.2.com/token?
  grant_type=client_credentials&  授权方式:凭证式
  client_id=CLIENT_ID&   客户端ID
  client_secret=CLIENT_SECRET 客户端密钥

2.返回令牌

https://1.com/callback#token=ACCESS_TOKEN

这种方式给出的令牌,是针对第三方应用的,而不是针对用户的,也就是说可能出现多个用户共享同一个令牌。

为什么要比较 JWT 和Oauth2 ,因为很多不明所以的人总是会在挑选技术的时候,会把二者拿出来对比,其实上,他们两个没有可比性,因为 JWT 是用于发布接入令牌,并对发布的签名接入令牌进行验证的方法。

OAuth2是一种授权框架,授权第三方应用访问特定资源。

也就是说:

  • OAuth2用在使用第三方账号登录的情况
  • JWT是用在前后端分离, 需要简单的对后台API进行保护

所以你知道怎么选择了么?

相关推荐

redis 7.4.3更新!安全修复+性能优化全解析

一、Redis是什么?为什么选择它?Redis(RemoteDictionaryServer)是一款开源的高性能内存键值数据库,支持持久化、多数据结构(如字符串、哈希、列表等),广泛应用于缓存、消...

C# 读写Redis数据库的简单例子

CSRedis是一个基于C#的Redis客户端库,它提供了与Redis服务器进行交互的功能。它是一个轻量级、高性能的库,易于使用和集成到C#应用程序中。您可以使用NuGet包管理器或使用以下命令行命令...

十年之重修Redis原理

弱小和无知并不是生存的障碍,傲慢才是。--------面试者总结Redis可能都用过,但是从来没有理解过,就像一个熟悉的陌生人,本文主要讲述了Redis基本类型的使用、数据结构、持久化、单线程模型...

高频L2行情数据Redis存储架构设计(含C++实现代码)

一、Redis核心设计原则内存高效:优化数据结构,减少内存占用低延迟访问:单次操作≤0.1ms响应时间数据完整性:完整存储所有L2字段实时订阅:支持多客户端实时数据推送持久化策略:RDB+AOF保障数...

Magic-Boot开源引擎:零代码玩转企业级开发,效率暴涨!

一、项目介绍基于magic-api搭建的快速开发平台,前端采用Vue3+naive-ui最新版本搭建,依赖较少,运行速度快。对常用组件进行封装。利用Vue3的@vue/compiler-sfc单文...

项目不行简历拉胯?3招教你从面试陪跑逆袭大厂offer!

项目不行简历拉胯?3招教你从面试陪跑逆袭大厂offer!老铁们!是不是每次面试完都感觉自己像被大厂面试官婉拒的渣男?明明刷了三个月题库,背熟八股文,结果一被问项目就支支吾吾,简历写得像大学生课程设计?...

谷歌云平台:开发者部署超120个开源包

从国外相关报道了解,Google与Bitnami合作为Google云平台增加了一个新的功能,为了方便开发人员快捷部署程序,提供了120余款开源应用程序云平台的支持。这些应用程序其中包括了WordPre...

知名互联网公司和程序员都看好的数据库是什么?

2017年数据库领域的最大趋势是什么?什么是最热的数据处理技术?学什么数据库最有前途?程序员们普遍不喜欢的数据库是什么?本文都会一一揭秘。大数据时代,数据库的选择备受关注,此前本号就曾揭秘国内知名互联...

腾讯云发布云存储MongoDB服务

近日,著名安全专家兼Shodan搜索引擎的创建者JohnMatherly发现,目前至少有35000个受影响的MongoDB数据库暴露在互联网上,它们所包含的数据暴露在网络攻击风险之中。据估计,将近6...

已跪,Java全能笔记爆火,分布式/开源框架/微服务/性能调优全有

前言程序员,立之根本还是技术,一个程序员的好坏,虽然不能完全用技术强弱来判断,但是技术水平一定是基础,技术差的程序员只能CRUD,技术不深的程序员也成不了架构师。程序员对于技术的掌握,除了从了解-熟悉...

面试官:举个你解决冲突的例子?别怂!用这个套路……

面试官:举个你解决冲突的例子?别怂!用这个套路……最近收到粉丝私信,说被问到:团队技术方案有分歧怎么办?当场大脑宕机……兄弟!这不是送命题,是展示你情商+技术判断力的王炸题!今天教你们3招,用真实案例...

面试碰到MongoDB?莫慌,跟面试官这样吹MongoDB 复制集

推荐阅读:吊打MySQL:21性能优化实践+学习导图+55面试+笔记+20高频知识点阿里一线架构师分享的技术图谱,进阶加薪全靠它十面字节跳动,依旧空手而归,我该放弃吗?文末会分享一些MongoDB的学...

SpringBoot集成扩展-访问NoSQL数据库之Redis和MongoDB!

与关系型数据库一样,SpringBoot也提供了对NoSQL数据库的集成扩展,如对Redis和MongoDB等数据库的操作。通过默认配置即可使用RedisTemplate和MongoTemplate...

Java程序员找工作总卡项目关?

Java程序员找工作总卡项目关?3招教你用真实经历写出HR抢着要的简历!各位Java老哥,最近刷招聘软件是不是手都划酸了?简历投出去石沉大海,面试邀请却总在飞别人的简历?上周有个兄弟,13年经验投了5...

Java多租户SaaS系统实现方案

嗯,用户问的是Java通过租户id实现的SaaS方案。首先,我需要理解用户的需求。SaaS,也就是软件即服务,通常是指多租户的架构,每个租户的数据需要隔离。用户可能想知道如何在Java中利用租户ID来...

取消回复欢迎 发表评论: