欢迎您访问 最编程 本站为您分享编程语言代码,编程技术文章!
您现在的位置是: 首页

深入理解会话、令牌、JWT 和 OAuth 2.0 的工作原理与应用

最编程 2024-07-28 10:32:32
...

我们在登录某一网站经常记录登录状态,或者访问第三方网站,不知道怎么实现交互的,以下具体分析几种方法,并对他们相互之间进行比较,包括Session、Token、JWT、OAuth2。 先以总结主要点引出细节。

从分类上说,

  • Session是一种认证机制
  • Token、JWT是认证授权机制
  • OAuth2是授权框架

从应用场景长说,

  • Session:自己的简单网站;
  • Token:分布式、跨系统、单点登录、允许第三方调用api接口、用户数据需要与第三方共享等不适合实现。
  • JWT:场景可以同Token,但是获取验证token的实现逻辑不一样
  • OAuth2:授权第三方应用、多平台单点登录

从具体实现来说,

  • Session:基于cookie和sessionId
  • Token的token: uid(用户唯一身份标识)+ timestamp(当前时间戳) + sign(签名)
  • JWT的token:header(头部) + payload(负载 )+ sign(签名)
  • OAuth2:基于授权码code、client_id、client_secret等

Session 和 Cookie的区别

  • 安全性: Session 比 Cookie 安全,Session 是存储在服务器端的,Cookie 是存储在客户端的。

  • 存取值的类型不同:Cookie 只支持存字符串数据,想要设置其他类型的数据,需要将其转换成字符串,Session 可以存任意数据类型。

  • 有效期不同: Cookie 可设置为长时间保持,比如我们经常使用的默认登录功能,Session 一般失效时间较短,客户端关闭(默认情况下)或者 Session 超时都会失效。

  • 存储大小不同: 单个 Cookie 保存的数据不能超过 4K,Session 可存储数据远高于 Cookie,但是当访问量过多,会占用过多的服务器资源。

Token和Session

会话信息

“会话信息”窗口显示当前登录到 Access Manager 的所有用户,并显示每个用户的会话时间。显示的字段包括:

用户 ID。 显示当前登录用户的用户 ID。

剩余时间。 显示需要重新验证之前,用户的该会话所剩余的时间(以分钟为单位)。

最长会话时间。 显示用户在会话过期而必须重新验证以重新获得访问权限之前可以登录的最长时间(以分钟为单位)。

空闲时间。显示用户处于空闲状态的时间(以分钟为单位)。

最长空闲时间。 显示用户在需要重新验证之前,可以处于空闲状态的最长时间(以分钟为单位)。

时间限制由管理员在“会话管理服务”中定义。

在“用户 ID”字段中输入字符串,然后单击“过滤”可以显示特定的用户会话或用户会话中特定的部分。允许输入通配符。

还可以查看登录源IP地址、登录时间、登出时间等详细信息。

token令牌,构成是:

  • uid:用户唯一身份标识
  • timestamp:当前时间戳
  • sign:签名字符串,防止第三方伪造数据;签名密钥是存储在服务器端的,其它人无法知道
  • 其它附加参数。

Token 和 Session 的区别

  • token是身份信息和签名生成的,是一个整体传给客户端;sessionId是毫无规则的随机数,由服务端在客户端登录通过后随即生产的。
  • 客户端: token和sessionId都可保存在Cookie、LocalStorage中。
  • 服务端:对于Token,私钥也就是签名保存在数据库中,但是不保一些存会话信息;sessionId及该id所代表的客户端信息都保存在内存或是数据库(通常是内存数据库)(通过sessionId从服务端查询它所代表的用户,既然是随即生产的,所以sessionId在服务端肯定也保存了)
  • token是通过响应体返回给客户端的,保存在cookie、localstorage等中,再次请求时不会默认携带,可以在请求头Authorization携带token;sessionId是服务端设置在cookie中,客户端每次请求会默认带上它
  • Session 是一种记录服务器和客户端会话状态的机制,使服务端有状态化,可以记录会话信息。而 Token 是令牌,访问资源接口(API)时所需要的资源凭证。Token 使服务端无状态化,不会存储会话信息。
  • Session 和 Token 并不矛盾,作为身份认证 Token 安全性比 Session 好,因为每一个请求都有签名还能防止监听以及重放攻击,而 Session 就必须依赖链路层来保障通讯安全了。如果你需要实现有状态的会话,仍然可以增加 Session 来在服务器端保存一些状态。
  • Token是令牌,代表执行某些操作的权限,如果指的是 OAuth Token 或类似的机制的话,提供的是 认证 和 授权,认证是针对用户,授权是针对 App,目的是让某 App 有权利访问某用户的信息。token 是唯一的。不可以转移到其它 App上,也不可以转到其它用户上;Session 只提供一种简单的认证,即只要有此 SessionID ,即认为有此 User 的全部权利。(所以简单来说:如果你的用户数据可能需要和第三方共享,或者允许第三方调用 API 接口,用 Token 。如果永远只是自己的网站,自己的 App,用什么就无所谓了。)

回想下数据链路层?因为为啥说session在链路层上保障安全?

为什么大部分选择Token不用Session?

  • 客户端浏览器只要保存自己的sessionID即可,而服务器却要保存所有用户的Session信息,这对于服务器来说开销较大,而且不利用服务器的扩展。

  • 另外sessionId保存在客户端,容易发起恶意请求,不安全,当然token签名不能被盗,被盗那也不安全,所以设置过期时间不能太长。

  • cookie/session在单服务器,单域名时比较简单,否则的话,就要考虑如何将客户端的session保存或同步到多个服务器。还要考虑一旦宕机,内存中的这些信息是否会丢失。token因为服务器不保存用户身份,就不存在这个问题,更利于分布式部署

总结

  • Cookie:保存在浏览器种,有大小限制,有状态;没有特殊限制cookie,客户端每次请求会默认带上它。

  • Session:保存在服务器中,服务器有资源开销,分布式、跨系统、单点登录、允许第三方调用api接口、用户数据需要与第三方共享等不适合实现;

  • Token:客户端可以将Token保存到任何地方,无限制,无状态,利于分布式部署。

  • sessionID 是连接 Cookie 和 Session 的一道桥梁

  • 如果只是自己的简单网站,倾向于使用session。如果系统同时登录用户多,集群服务器多,有单点登录需求,则倾向于使用token。

JWT

什么是 JWT

  • JSON Web Token(简称 JWT)是目前最流行的跨域认证解决方案
  • JWT 是为了在网络应用环境间传递声明而执行的一种基于 JSON 的开放标准(RFC 7519)。JWT 的声明一般被用来在身份提供者和服务提供者间传递被认证的用户身份信息,以便于从资源服务器获取资源。比如用在用户登录上。
  • 可以使用 HMAC 算法或者是 RSA 的公/私秘钥对 JWT 进行签名。因为数字签名的存在,这些传递的信息是可信的。

WT (Web Token)

WT包含三个部分: Header头部,Payload负载和Signature签名。由三部分生成token,三部分之间用“.”号做分割。

  1. Header 在Header中通常包含了两部分:type:代表token的类型,这里使用的是JWT类型。 alg:使用的Hash算法,例如HMAC SHA256或RSA。

    { "alg": "HS256", "typ": "JWT" } 这会被经过base64Url编码形成第一部分

  2. Payload token的第二个部分是荷载信息,它包含一些声明Claim(实体的描述,通常是一个User信息,还包括一些其他的元数据) 声明分三类:

  • Reserved Claims,这是一套预定义的声明,并不是必须的,这是一套易于使用、操作性强的声明。包括:iss(issuer)、exp(expiration time)、sub(subject)、aud(audience)等 ;
  • Plubic Claims;
  • Private Claims,交换信息的双方自定义的声明 { "sub": "1234567890", "name": "John Doe", "admin": true } 同样经过Base64Url编码后形成第二部分
  1. signature 使用header中指定的算法将编码后的header、编码后的payload、一个secret进行加密。 例如使用的是HMAC SHA256算法,大致流程类似于: HMACSHA256( base64UrlEncode(header) + "." + base64UrlEncode(payload), secret) 这个signature字段被用来确认JWT信息的发送者是谁,并保证信息没有被修改 。

JWT 认证流程

  • 用户输入用户名/密码登录,服务端认证成功后,会返回给客户端一个 JWT
  • 客户端将 token 保存到本地(通常使用 localstorage,也可以使用 cookie)
  • 当用户希望访问一个受保护的路由或者资源的时候,需要请求头的 Authorization 字段中使用Bearer 模式添加 JWT,其内容看起来是下面这样

Authorization: Bearer

Token 和 JWT 的区别

相同:

  • 都是认证授权机制(也可以说都是令牌),只有验证成功后,客户端才能访问服务端上受保护的资源
  • 都可以记录用户的信息
  • 都是在服务端无状态化的认证机制,因为用户的状态不再存储在服务端的内存中

区别:

  1. 得出token算法不一样

token包含: uid(用户唯一身份标识)+ timestamp(当前时间戳) + sign(签名)

WT包含:header(头部) + payload(负载 )+ sign(签名)

  1. 在客户端存储位置

一般,JWT 并不使用 Cookie,放在请求头 Authorization中,Token存储在Cookie中。

因为JWT不使用 Cookie 的,所以你可以使用任何域名提供你的 API 服务而不需要担心跨域资源共享问题(CORS)

  1. 是否需要查询数据库
  • Token:服务端验证客户端发送过来的 Token 时,还需要查询数据库获取用户信息,然后验证 Token 是否有效
  • JWT: 将 Token 和 Payload 加密后存储于客户端,服务端只需要使用密钥解密进行校验(校验也是 JWT 自己实现的)即可,不需要查询或者减少查询数据库,因为 JWT 自包含了用户信息和加密的数据。

用一句话总结最大区别:Token是需要查询数据库,JWT不要查询,直接用秘钥在服务端进行校验。

OAuth

在OAuth2.0中“O”是Open的简称,表示“开放”的意思。Auth表示“授权”的意思,所以连起来OAuth表示“开放授权”的意思,它是一个关于授权(authorization)的开放网络标准,在全世界得到广泛应用。用一句话总结来说,OAuth2.0是一种授权协议。

OAuth允许用户授权第三方应用访问他存储在另外服务商里的各种信息数据,而这种授权不需要提供用户名和密码提供给第三方应用

eg: 飞书中开发的应用在飞书中免登录

总的来说:OAuth2.0这种授权协议,就是保证第三方应用只有在获得授权之后,才可以进一步访问授权者的数据。

第三方应用先申请获取一个授权码,然后再使用该授权码获取令牌,最后使用令牌获取资源;授权码模式是工能最完整、流程最严密的授权模式。它的特点是通过客户端的后台服务器,与服务提供商的认证服务器进行交互。

飞书用的免登录也是OAuth2.0逻辑

function getCode() {
    let code = getUrlParam("code");
    console.log("code:", code);
    if (code) {
      getUseInfo(code);
    } else {
      window.location.href =
        "https://open.work.sany.com.cn/open-apis/authen/v1/user_auth_page?app_id=cli_a0b221d078389076&redirect_uri=http%3A%2F%2F222.240.242.218%3A8888%2Fdevice%2F";
    }
  }

授权码code时间特别短,飞书就仅仅设置了1分钟,之前在得到是2分钟。

拿到授权码,我们的服务端会去认证服务器请求数据。

https://server.example.com/oauth/token?client_id=CLIENT_ID&client_secret=CLIENT_SECRET&grant_type=authorization_code&code=AUTHORIZATION_CODE&redirect_uri=CALLBACK_URL

请求参数解释:

  • client_id:客户端id,第三方应用在服务提供者平台注册的;
  • client_secret:授权服务器的秘钥,第三方应用在服务提供者平台注册的;
  • grant_type:值是AUTHORIZATION_CODE,表示采用的授权方式是授权码;
  • code:表示上一步获得的授权码;
  • redirect_uri:redirect_uri参数是令牌颁发后的回调网址,且必须与A步骤中的该参数值保持一致;

注:client_id参数和client_secret参数用来让 B 确认 A 的身份(client_secret参数是保密的,因此只能在后端发请求)

公司这么多应用平台就可以用OAuth,这样只要登录一个用户就行,其他应用都免登录。

OAuth2.0的授权模式

  • 授权码模式(authorization code)
  • 简化模式(implicit)
  • 密码模式(resource owner password credentials)
  • 客户端模式(client credentials)

具体实现逻辑参考:www.jianshu.com/p/a0905113b…

JWT和OAuth2的区别

  1. 功能属性不一样
  • JWT是一种认证协议,验证用户对资源是否可以访问
  • OAuth2是一种授权框架,提供了一套详细的授权机制(指导),可以授权第三方应用访问特定资源。
  1. 应用场景不一样
  • JWT是用在前后端分离, 需要简单的对后台API进行保护时使用
  • OAuth2用在使用第三方账号登录的情况(比如使用weibo, qq, github登录某个app)

OAuth2是一个相对复杂的协议, 有4种授权模式, 其中的access code模式在实现时可以使用jwt生成code, 也可以不用,它们之间没有必然的联系;OAuth2有client和scope的概念,jwt没有。

很多情况下,在讨论OAuth2的实现时,会把JSON Web Token作为一种认证机制使用

我的总结

我们在登录某一网站经常记录登录状态,或者访问第三方网站,不知道怎么实现交互的,以上具体分析几种方法,并对他们相互之间进行比较,包括Session、Token、JWT、OAuth2。

从分类上说,

  • Session是一种认证机制
  • Token、JWT是认证授权机制
  • OAuth2是授权框架

从应用场景长说,

  • Session:自己的简单网站;
  • Token:分布式、跨系统、单点登录、允许第三方调用api接口、用户数据需要与第三方共享等不适合实现。
  • JWT:场景可以同Token,但是获取验证token的实现逻辑不一样
  • OAuth2:授权第三方应用、多平台单点登录

从具体实现来说,

  • Session:基于cookie和sessionId
  • Token的token: uid(用户唯一身份标识)+ timestamp(当前时间戳) + sign(签名)
  • JWT的token:header(头部) + payload(负载 )+ sign(签名)
  • OAuth2:基于授权码code、client_id、client_secret等

注意点:

  • cookie不是身份认证方式的一种,session、token都可基于它实现认证。

  • 认证是针对用户,授权是针对App或者网址。

www.jianshu.com/p/f31ef35eb…

推荐阅读