一次性弄清楚 Authentication & Authorization 以及 Cookie、Session、Token

简介: 老虎、老鼠、傻傻分不清楚?满脸、泥土、失败的被俘虏!通过本文学习,让我们一次性搞清楚 Authentication & Authorization 以及 Cookie、Session、Token 的区别与联系。

认证和授权的区别是什么?

不出意外情况,我想这是一个绝大多数人都会混淆的问题。首先先从读音上来认识这两个名词,很多人都会把它俩的读音搞混,所以我建议你先先去查一查这两个单词到底该怎么读,他们的具体含义是什么。

说简单点就是:

  • 认证 (Authentication): 你是谁?Who are you?
  • 授权 (Authorization): 你有权限干什么?What do you have access to do?

稍微正式点(啰嗦点)的说法就是:

  • Authentication(认证) 是验证您的身份的凭据(例如用户名/用户ID和密码),通过这个凭据,系统得以知道你就是你,也就是说系统存在你这个用户。所以,Authentication 被称为身份/用户验证。
  • Authorization(授权) 发生在 Authentication(认证)之后。授权嘛,光看意思大家应该就明白,它主要掌管我们访问系统的权限。比如有些特定资源只能具有特定权限的人才能访问比如admin,有些对系统资源操作比如删除、添加、更新只能特定人才具有。

这两个一般在我们的系统中被结合在一起使用,目的就是为了保护我们系统的安全性

举个简单的例子🌰:比如工作牌就是 Authentication(认证)你是谋谋公司,机构或组织的身份标识和凭据,根据这个凭据即可进入该单位区域工作,比如刷卡进出大门;而你个人的工作岗位和职责就类似Authorization(授权),单位授权该岗位能干些什么范围的工作;

重新认识 Cookie

什么是 Cookie,以及它的作用是什么?

Cookie 有时也用其复数形式 Cookies,存储类型为“小型文本文件”,是某些网站为了辨别用户身份,进行 Session 跟踪而储存在用户本地终端上的数据(通常经过加密),由用户客户端计算机暂时或永久保存的信息。

Cookie 特点:

  1. 存储结构:以 Key-Value 形式存储的“小型文本文件”;
  2. 存储位置:存储在用户终端的某个目录下;
  3. 存储大小:≤ 4KB
  4. 时效性:可暂时或永久性保存,用户终端自行决定;

Cookie是一段不超过 4KB 的小型文本数据,由一个名称(Name)、一个值(Value)和其它几个用于控制 Cookie 有效期、安全性、使用范围的可选属性组成。

属性 说明
Name/Value 设置 Cookie 的名称及相对应的值,对于认证 Cookie,Value 值包括 Web 服务器所提供的访问令牌。
Expires 设置 Cookie 的生存期。 有两种存储类型的 Cookie:会话性与持久性。Expires 属性缺省时,为会话性 Cookie,仅保存在客户端内存中,并在用户关闭浏览器时失效;持久性 Cookie 会保存在用户的硬盘中,直至生存期到或用户直接在网页中单击“注销”等按钮结束会话时才会失效。
Path 定义了 Web 站点上可以访问该 Cookie 的目录。
Domain 指定了可以访问该 CookieWeb 站点或域。Cookie 机制并未遵循严格的同源策略,允许一个子域可以设置或获取其父域的 Cookie。当需要实现单点登录方案时,Cookie 的上述特性非常有用,然而也增加了 Cookie 受攻击的危险,比如攻击者可以借此发动会话定置攻击。因而,浏览器禁止在 Domain 属性中设置 .org、.com 等通用顶级域名、以及在国家及地区顶级域下注册的二级域名,以减小攻击发生的范围。
Secure 指定是否使用 HTTPS 安全协议发送 Cookie。使用 HTTPS 安全协议,可以保护 Cookie 在浏览器和 Web 服务器间的传输过程中不被窃取和篡改。该方法也可用于 Web 站点的身份鉴别,即在 HTTPS 的连接建立阶段,浏览器会检查 Web 网站的 SSL 证书的有效性。但是基于兼容性的原因(比如有些网站使用自签署的证书)在检测到 SSL 证书无效时,浏览器并不会立即终止用户的连接请求,而是显示安全风险信息,用户仍可以选择继续访问该站点。由于许多用户缺乏安全意识,因而仍可能连接到 Pharming 攻击所伪造的网站。
HTTPOnly 用于防止客户端脚本通过 document.cookie 属性访问 Cookie ,有助于保护 Cookie 不被跨站脚本攻击窃取或篡改。但是,HTTPOnly 的应用仍存在局限性,一些浏览器可以阻止客户端脚本对 Cookie 的读操作,但允许写操作;此外大多数浏览器仍允许通过 XMLHTTP 对象读取 HTTP 响应中的 Set-Cookie 头。

如何使用 Cookie ?

HTTP 协议中的 Cookie 包括 Web Cookie 和 浏览器 Cookie,它是服务器发送到 Web 浏览器的一小块数据。服务器发送到浏览器的 Cookie,浏览器会进行存储,并与下一个请求一起发送到服务器。通常,它用于判断两个请求是否来自于同一个浏览器,例如用户保持登录状态。HTTP Cookie 机制是 HTTP 协议无状态的一种补充和改良。

Cookie 主要用于下面三个目的:

  • 会话管理:登陆、购物车、游戏得分或者服务器应该记住的其他内容;
  • 个性化:用户偏好、主题或者其他设置;
  • Session 追踪:记录和分析用户行为;

Cookie 应用:

  • 创建 Cookie:当接收到客户端发出的 HTTP 请求时,服务器可以发送带有响应的标头,Cookie 通常由浏览器存储,然后将 Cookie 与 HTTP 标头一同向服务器发出请求。
  • Set-Cookie 和 Cookie 标头:Set-Cookie 标头告诉客户端存储 Cookie,响应标头将 cookie 从服务器发送到用户代理;客户端请求则使用 Cookie 头将存储的 Cookie 发送回服务器;

下面是 Cookie 的一些应用案例:

  • 我们在 Cookie 中保存已经登录过的用户信息,下次访问网站的时候页面可以自动帮你登录的一些基本信息给填了。除此之外,Cookie 还能保存用户首选项,主题和其他设置信息。
  • 使用 Cookie 保存 Session 或者 Token ,向后端发送请求的时候带上 Cookie,这样后端就能取到 Session 或者 token 了。这样就能记录用户当前的状态了,因为 HTTP 协议是无状态的。
  • Cookie 还可以用来记录和分析用户行为。举个简单的例子你在网上购物的时候,因为 HTTP 协议是没有状态的,如果服务器想要获取你在某个页面的停留状态或者看了哪些商品,一种常用的实现方式就是将这些信息存放在Cookie。

什么是 Session ?

Session 简介

在计算机中,尤其是在网络应用中,通常称为“会话控制”。Session 对象存储特定用户会话所需的属性及配置信息。这样,当用户在应用程序的 Web 页之间跳转时,存储在 Session 对象中的变量将不会丢失,而是在整个用户会话中一直存在下去。当用户请求来自应用程序的 Web 页时,如果该用户还没有会话,则 Web 服务器将自动创建一个 Session对象。当会话过期或被放弃后,服务器将终止该会话。

Session 的主要作用就是通过服务端记录用户的状态。用于保持状态的基于 Web 服务器的方法。Session 允许通过将对象存储在 Web 服务器的内存中在整个用户会话过程中保持任何对象。

Session 的一些应用案例:

  • 存储用户的首选项。例如,如果用户指明不喜欢查看图形,就可以将该信息存储在 Session 对象中。
  • 典型的场景是购物车,当你要添加商品到购物车的时候,系统不知道是哪个用户操作的,因为 HTTP 协议是无状态的。服务端给特定的用户创建特定的 Session 之后就可以标识这个用户并且跟踪这个用户了。

Cookie 和 Session 有什么区别?

由于 HTTP 协议无状态的缺陷。WEB 的设计者们提出了 CookieSession 两种解决机制。
通过对两者的比较分析,指出了它们的区别与联系。

—— Cookie Session
效期 暂时和永久 常规暂时(也可实现永久)
存储 用户终端/客户端浏览器 服务器(Session + SessionID)
结构 key-value key-value
优点 1.极高的扩展性和可用性。
2.通过良好的编程,控制保存在cookie中的session对象的大小。
3.通过加密和安全传输技术(SSL),减少cookie被破解的可能性。
4.只在cookie中存放不敏感数据,即使被盗也不会有重大损失。
5.控制cookie的生命期,使之不会永远有效。偷盗者很可能拿到一个过期的cookie。

1.如果要在诸多Web页间传递一个变量,那么用Session变量要比通过QueryString传递变量可使问题简化。
2.要使WEb站点具有用户化,可以考虑使用Session变量。你的站点的每位访问者都有用户化的经验,基于此,随着LDAP和诸如MS Site
3.Server等的使用,已不必再将所有用户化过程置入Session变量了,而这个用户化是取决于用户喜好的。
4.你可以在任何想要使用的时候直接使用session变量,而不必事先声明它,这种方式接近于在VB中变量的使用。使用完毕后,也不必考虑将其释放,因为它将自动释放。

5.Session实例是轻量级的,所谓轻量级:是指他的创建和删除不需要消耗太多资源;

功能缺陷 1.Cookie数量和长度的限制。每个domain最多只能有20条cookie,每个cookie长度不能超过4KB,否则会被截掉。
2.安全性问题。如果cookie被人拦截了,那人就可以取得所有的session信息。即使加密也与事无补,因为拦截者并不需要知道cookie的意义,他只要原样转发cookie就可以达到目的了。
3.有些状态不可能保存在客户端。例如,为了防止重复提交表单,我们需要在服务器端保存一个计数器。如果我们把这个计数器保存在客户端,那么它起不到任何作用。

1.进程依赖性,ASP Session状态存于IIS的进程中,也就是inetinfo.exe这个程序。所以当inetinfo.exe进程崩溃时,这些信息也就丢失。另外,重起或者关闭IIS服务都会造成信息的丢失。

2.CORS(跨域资源共享):Session状态使用范围的局限性,当一个用户从一个网站访问到另外一个网站时,这些Session信息并不会随之迁移过去。

3.存在Cookie的依赖性,实际上客户端的Session信息是存储在Cookie中的,如果客户端完全禁用掉了Cookie功能,也就不能享受到了Session提供的功能了。

4.每次认证用户发起请求时,服务器需要去创建一个记录来存储信息。当越来越多的用户发请求时,内存的开销也会不断增加;

5.不是线程安全的,应该避免多个线程共享同一个Session实例。

安全

安全性相对较低;

1.Cookie捕获/重放;

2.恶意 Cookies;

3.会话定置(Session Fixation)攻击;

4.跨站请求伪造(Cross-Site Request Forgery,简称CSRF)攻击;

安全性相对较高;

1.web服务器防护;

2.主机安全防护;

3.跨站请求伪造(Cross-Site Request Forgery,简称CSRF)攻击;

因为创建 Session 变量有很大的随意性,可随时调用,不需要开发者做精确地处理,所以过度使用 Session 变量将会导致代码可读性降低,使项目维护困难。

理解 SessionID 的本质

  • 客户端使用 Cookie 保存 SessionID

客户端用 Cookie 保存了 SessionID,当我们请求服务器的时候,会把这个 SessionID 一起发给服务器,服务器会到内存中搜索对应的 SessionID,如果找到了对应的 SessionID,说明我们处于登录状态,有相应的权限;如果没有找到对应的 SessionID,这说明:要么是我们把浏览器关掉了(后面会说明为什么),要么 session 超时了(没有请求服务器超过 20 分钟),session 被服务器清除了,则服务器会给你分配一个新的 SessionID。你得重 新登录并把这个新的 SessionID 保存在 Cookie 中。
在没有把浏览器关掉的时候(这个时候假如已经把 SessionID 保存在 Cookie 中了)这个 SessionID 会一直保存在浏览器中,每次请求的时候都会把这个 SessionID 提交到服务器,所以服务器认为我们是登录的;当然,如果太长时间没有请求服务器,服务器会认为我们已经所以把浏览器关掉了,这个时候服务器会把该 SessionID 从内存中清除掉,这个时候如果我们再去请求服务器,SessionID 已经不存在了,所以服务器并没有在内存中找到对应的 SessionID,所以会再产生一个新的 SessionID,这个时候一般我们又要再登录一次。

  • 客户端未使用 Cookie 保存 SessionID

此时如果我们请求服务器,因为没有提交 SessionID 上来,服务器会认为你是一个全新的请求,服务器会给你分配一个新的 SessionID,这就是为什么我们每次打开一个新的浏览器的时候(无论之前我们有没有登录过)都会产生一个新的 SessionID(或者是会让我们重新登录)。当我们一旦把浏览器关掉后,再打开浏览器再请求该页面,它会让我们登录,这是为什么?我们明明已经登录了,而且还没有超时,SessionID 肯定还在服 务器上的,为什么现在我们又要再一次登录呢?这是因为我们关掉浏览再请求的时候,我们提交的信息没有把刚才的 SessionID 一起提交到服务器,所以服务器不知道我们是同一个人,所以这时服务器又为我们分配一个新的 SessionID

打个比方:浏览器就好像一个要去银行开户的人,而服务器就好比银行, 这个要去银行开户的人这个时候显然没有帐号( SessionID),所以到银行后,银行工作人员问有没有帐号,他说没有,这个时候银行就会为他开通一个帐号。所以可以这么说,每次打开一个新的浏览器去请求的一个页面的时候,服务器都会认为,这是一个新的请求,他为你分配一个新的 SessionID

基于以上问题,于是有人就会思考,服务器为什么要保存这些信息呢, 只让每个客户端去保存该多好?服务端只需把关好验证即可,因此在这种情况下,Token 应用而生。

关于 Token 的理解

什么是 Token ?

Token 是在服务端产生的。如果前端使用用户名/密码向服务端请求认证,服务端认证成功,那么在服务端会返回 Token 给前端。前端可以在每次请求的时候带上 Token 证明自己的合法地位。

  • Token 的引入Token 是在客户端频繁向服务端请求数据,服务端频繁的去数据库查询用户名和密码并进行对比,判断用户名和密码正确与否,并作出相应提示,在这样的背景下,Token 便应运而生。
  • Token 的定义Token 是服务端生成的一串字符串,以作客户端进行请求的一个令牌,当第一次登录后,服务器生成一个 Token 便将此 Token 返回给客户端,以后客户端只需带上这个 Token 前来请求数据即可,无需再次带上用户名和密码。
  • 使用 Token 的目的Token 的目的是为了减轻服务器的压力,减少频繁的查询数据库,使服务器更加健壮。

什么是 JWT?

说到 Token 我们不得不谈 JWT,Why...?

JWTJSON Web Token 的缩写,是目前最流行的跨域认证解决方案。

image.png

关于跨域认证的问题

互联网服务离不开用户认证。一般流程是下面这样。

  1. 用户向服务器发送用户名和密码。
  2. 服务器验证通过后,在当前对话(session)里面保存相关数据,比如用户角色、登录时间等等。
  3. 服务器向用户返回一个 session_id,写入用户的 Cookie
  4. 用户随后的每一次请求,都会通过 Cookie,将 session_id 传回服务器。
  5. 服务器收到 session_id,找到前期保存的数据,由此得知用户的身份。

这种模式的问题在于,扩展性(scaling)不好。单机当然没有问题,如果是服务器集群,或者是跨域的服务导向架构,就要求 session 数据共享,每台服务器都能够读取 session

  • 举例说明:

A 网站和 B 网站是同一家公司的关联服务。现在要求,用户只要在其中一个网站登录,再访问另一个网站就会自动登录,请问怎么实现?

  1. 一种解决方案是 session 数据持久化,写入数据库或别的持久层。各种服务收到请求后,都向持久层请求数据。这种方案的优点是架构清晰,缺点是工程量比较大。另外,持久层万一挂了,就会单点失败。
  2. 另一种方案是服务器索性不保存 session 数据了,所有数据都保存在客户端,每次请求都发回服务器。JWT 就是这种方案的一个代表。

JWT 的原理

JWT 的原理是,服务器认证以后,生成一个 Base64URL 编码后的 JSON 对象,发回给用户,JSON 明文信息如下(后面叙述)。

以后,用户与服务端通信的时候,都要发回这个 JSON 对象。服务器完全只靠这个对象认定用户身份。为了防止用户篡改数据,服务器在生成这个对象的时候,会加上签名(详见后文)。

服务器就不保存任何 session 数据了,也就是说,服务器变成无状态了,从而比较容易实现扩展。

JWT 的数据结构

  • Header(头部):是一个 JSON 对象,描述 JWT 的元数据;
  • Payload(负载):也是一个 JSON 对象,用来存放实际需要传递的数据;
  • Signature(签名):对前两部分的签名,防止数据篡改;
说明: JWT 实际是一个很长的字符串,分别由【 Header.Payload.Signature】组成,注意中间使用【.】分隔成三个部分。
  1. Header(头部)通常如下对象:
{
  "alg": "HS256", //alg属性表示签名的算法(algorithm),默认是 HMAC SHA256(写成 HS256)
  "typ": "JWT" //typ属性表示这个令牌(token)的类型(type),JWT 令牌统一写为JWT
}
  1. Payload(负载)JWT 规定了 7 个官方字段,供选用:
  • iss (issuer):签发人
  • exp (expiration time):过期时间
  • sub (subject):主题
  • aud (audience):受众
  • nbf (Not Before):生效时间
  • iat (Issued At):签发时间
  • jti (JWT ID):编号

除了上面官方规定的字段,你还可以在这个部分自定义私有字段,下面就是一个例子:

{
  "sub": "1234567890",
  "name": "chait",
  "admin": true
}
注意:JWT 默认是不加密的,任何人都可以读到,所以不要把秘密信息放在这个部分。
  1. Signature(签名)

首先,需要指定一个密钥(secret),这个密钥只有服务器才知道,不能泄露给用户。
然后,使用 Header 里面指定的签名算法(默认是 HMAC SHA256),按照下面的公式产生签名:

HMACSHA256(base64UrlEncode(header) + "." + base64UrlEncode(payload), secret)

算出签名以后,把 Header(Base64URL编码)、Payload(Base64URL编码)、Signature 三个部分拼成一个字符串,每个部分之间用"点"(.)分隔,就可以返回给用户。

  • Base64URL 算法

前面提到,Header 和 Payload 串型化的算法是 Base64URL

这个算法跟 Base64 算法基本类似,但有一些小的不同,区别如下:

JWT 作为一个令牌(token),有些场合可能会放到 URL(比如 api.example.com/?token=xxx)。Base64 有三个字符+、/和=,在 URL 里面有特殊含义,所以要被替换掉:=被省略、+替换成-,/替换成_

JWT 的使用方式

  • 客户端接收到服务器返回的 JWT,可以存储在 CookieLocal Storage
  • 客户端每次与服务器通信,都要带上这个 JWT

你可以把它放在 Cookie 里面自动发送,但是这样不能跨域,针对跨域提供两种方案:

  • 更好的做法是放在 HTTP 请求的头信息【Authorization】字段里面或者是自定义约定字段;
  • JWT 就放在 POST 请求的数据体里面;

JWT 的几个特点

(1)JWT 默认是不加密,但也是可以加密的。生成原始 Token 以后,可以用密钥再加密一次。
(2)JWT 不加密的情况下,不能将秘密数据写入 JWT。
(3)JWT 不仅可以用于认证,也可以用于交换信息。有效使用 JWT,可以降低服务器查询数据库的次数。
(4)JWT 的最大缺点是,由于服务器不保存 session 状态,因此无法在使用过程中废止某个 token,或者更改 token 的权限。也就是说,一旦 JWT 签发了,在到期之前就会始终有效,除非服务器部署额外的逻辑。
(5)JWT 本身包含了认证信息,一旦泄露,任何人都可以获得该令牌的所有权限。为了减少盗用,JWT 的有效期应该设置得比较短。对于一些比较重要的权限,使用时应该再次对用户进行认证。
(6)为了减少盗用,JWT 不应该使用 HTTP 协议明码传输,要使用 HTTPS 协议传输。

基于 Token 的身份验证原理

基于 Token 的身份验证是无状态的,我们不用将用户信息存在服务器或 Session 中。这种概念解决了在服务端存储信息时的许多问题。没有 session 信息意味着你的程序可以根据需要去增减机器,而不用去担心用户是否登录和已经登录到了哪里。

虽然基于 Token 的身份验证实现的方式很多,但大致过程如下:

  1. 用户通过用户名和密码发送请求。
  2. 程序验证。
  3. 程序返回一个签名的 token 给客户端。
  4. 客户端储存 token, 并且每次请求都会附带它。
  5. 服务端验证 token 并返回数据。

每一次请求都需要 TokenToken 应该在 HTTP的头部发送从而保证了 Http 请求无状态。
我们也需要设置服务器属性 【Access-Control-Allow-Origin: * 】来让服务器能接受到来自所有域的请求。

需要注意的是,在 ACAO 头部指定 * 时,不得带有像 HTTP 认证,客户端 SSL 证书和 cookies 的证书。

执行流程如下:

image.png

执行流程说明:

  1. 用户登录校验,校验成功后就返回 Token 给客户端。
  2. 客户端收到 Token 以后可以把它存储起来,比如放在 localStorage 中。
  3. 客户端每次访问 API 都(通常 http 请求头)携带 Token 到服务器端。
  4. 服务器端采用 filter 过滤器校验。校验成功则返回请求数据,校验失败则返回错误码。

当我们在程序中认证了信息并取得 token 之后,我们便能通过这个 token 做许多的事情。我们甚至能基于创建一个基于权限的 token 传给第三方应用程序,这些第三方程序能够获取到我们的数据(当然只限于该 token 被允许访问的数据)。

Tokens 的优势和缺陷

那么相对于 Cookie 和 Session,Token 有哪些优缺点呢?

1、Token 的优势

  • 支持跨域访问: Cookie 是不允许垮域访问的,token 支持;
  • 无状态、可扩展: token 无状态,session 有状态的;
  • 去耦: 不需要绑定到一个特定的身份验证方案。Token可以在任何地方生成,只要在 你的API被调用的时候, 你可以进行 Token 生成调用即可.
  • 多平台支持: Cookie 不支持手机端访问的,token 支持,更适用于移动应用;
  • 基于标准化: 你的 API 可以采用标准化的 JSON Web Token (JWT)。这个标准已经存在多个后端库(.NET,Ruby,Java,Python,PHP 等)和多家公司的支持(如:Firebase,Google,Microsoft 等);

2、Token 的缺陷

  • 带宽占用:正常情况下要比 session_id 更大,需要消耗更多流量,挤占更多带宽,假如你的网站每月有 10 万次的浏览器,就意味着要多开销几十兆的流量。听起来并不多,但日积月累也是不小一笔开销。实际上,许多人会在 JWT 中存储的信息会更多。
  • 安全隐患:无法在服务端注销,服务器一旦生产 Token 并下发客户端,在 Token 有效期内很难解决劫持问题。
  • 性能问题:JWT 的卖点之一就是加密签名,由于这个特性,接收方得以验证 JWT 是否有效且被信任。但是大多数 Web 身份认证应用中,JWT 都会被存储到 Cookie 中,这就是说你有了两个层面的签名。听着似乎很牛逼,但是没有任何优势,为此,你需要花费两倍的 CPU 开销来验证签名。对于有着严格性能要求的 Web 应用,这并不理想,尤其对于单线程环境。

关于 JWT、JWS 与 JWE 的区别,此处不再详述,请自行查看 => https://blog.csdn.net/ChaITSimpleLove/article/details/120178667

目录
相关文章
|
1月前
|
存储 自然语言处理 API
Session、cookie、token有什么区别?
Session、cookie、token有什么区别?
24 1
|
2月前
|
存储 开发框架 NoSQL
ASP.NET WEB——项目中Cookie与Session的用法
ASP.NET WEB——项目中Cookie与Session的用法
29 0
|
3天前
|
存储 JSON 安全
|
1月前
|
数据采集 存储 安全
登录态数据抓取:Python爬虫携带Cookie与Session的应用技巧
登录态数据抓取:Python爬虫携带Cookie与Session的应用技巧
|
1月前
|
存储 安全 搜索推荐
Django中Cookie和Session的使用
Django中Cookie和Session的使用
21 0
|
1月前
|
存储 安全 对象存储
Cookie和Session的区别:从原理到应用
【2月更文挑战第18天】
54 6
|
1月前
|
存储 搜索推荐 安全
【Web开发】cookie和session
【Web开发】cookie和session
|
2月前
|
存储 搜索推荐 安全
Java Web开发中的会话管理:Cookie与Session对比
Java Web开发中的会话管理:Cookie与Session对比
|
2月前
|
存储 前端开发 Java
【JavaEE进阶】 获取Cookie和Session
【JavaEE进阶】 获取Cookie和Session
|
2月前
|
存储 安全 API
Cookie,Session和Token
Cookie,Session和Token