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

1. 认证 (Authentication) 和授权 (Authorization)的区别是什么?

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

说简单点就是:

  • 认证 (Authentication) 你是谁?
  • 授权 (Authorization) 你有权限干什么?

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

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

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

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

2. 什么是Cookie ? Cookie的作用是什么? 以及如何使用 Cookie ?

2.1 什么是 Cookie ? Cookie 的作用是什么?

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

特点

1.存储结构:以KV形式存储的“小型文本文件”;

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属性指定了可以访问该 Cookie 的 Web 站点或域。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头。

2.2 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 的一些应用案例:

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

3. 什么是 Session ?Cookie 和 Session 有什么区别?如何使用 Session 进行身份验证?

3.1 Session 简介

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

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

Session 的一些应用案例:

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

3.2 Cookie 和 Session 的区别

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

——CookieSession
效期暂时和永久常规暂时(也可实现永久)
存储用户终端/客户端浏览器服务器(Session + SessionID)
结构key-valuekey-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 变量将会导致代码可读性降低,使项目维护困难。

3.3 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 应用而生。

4. 什么是 Token? 什么是 JWT? 如何基于Token进行身份验证?

4.1 什么是 Token?

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

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

4.2 什么是 JWT? 

JSON Web Token(缩写 JWT)是目前最流行的跨域认证解决方案

4.2.1 跨域认证的问题

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

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

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

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

一种解决方案是 session 数据持久化,写入数据库或别的持久层。各种服务收到请求后,都向持久层请求数据。这种方案的优点是架构清晰,缺点是工程量比较大。另外,持久层万一挂了,就会单点失败。

另一种方案是服务器索性不保存 session 数据了,所有数据都保存在客户端,每次请求都发回服务器。JWT 就是这种方案的一个代表。

4.2.2 JWT 的原理

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

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

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

4.2.3 JWT 的数据结构

  • Header(头部):是一个 JSON 对象,描述 JWT 的元数据;
  • Payload(负载):也是一个 JSON 对象,用来存放实际需要传递的数据;
  • Signature(签名):对前两部分的签名,防止数据篡改;

JWT 实际是一个很长的字符串,分别由【Header.Payload.Signature】组成,注意中间使用【.】分隔成三个部分。

Header(头部)通常如下对象:

{
  "alg": "HS256", //alg属性表示签名的算法(algorithm),默认是 HMAC SHA256(写成 HS256)
  "typ": "JWT" //typ属性表示这个令牌(token)的类型(type),JWT 令牌统一写为JWT
}

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 默认是不加密的,任何人都可以读到,所以不要把秘密信息放在这个部分。

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 里面有特殊含义,所以要被替换掉:=被省略、+替换成-,/替换成_ 。

4.2.4 JWT 的使用方式

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

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

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

4.2.5 JWT 的几个特点

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

4.3  基于 Token 的身份验证原理

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

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

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

每一次请求都需要Token。Token 应该在 HTTP的头部发送从而保证了 Http 请求无状态。
我们也需要设置服务器属性 【Access-Control-Allow-Origin: * 】来让服务器能接受到来自所有域的请求。
需要注意的是,在ACAO头部指定 * 时,不得带有像HTTP认证,客户端SSL证书和cookies的证书。

执行流程如下:

  • 1.用户登录校验,校验成功后就返回Token给客户端。
  • 2.客户端收到数据后保存在客户端
  • 3.客户端每次访问API是携带Token到服务器端。
  • 4.服务器端采用filter过滤器校验。校验成功则返回请求数据,校验失败则返回错误码。

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

4.4  Tokens 的优势

(1)无状态、可扩展

  • 在客户端存储的 token 是无状态的,并且能够被扩展。基于这种无状态和不存储Session信息,负载均衡服务器 能够将用户的请求传递到任何一台服务器上,因为服务器与用户信息没有关联。相反在传统方式中,我们必须将请求发送到一台存储了该用户 session 的服务器上(称为Session亲和性),因此当用户量大时,可能会造成 一些拥堵。使用 token 完美解决了此问题。

(2)安全性

  • 请求中发送 token 而不是 cookie,这能够防止 CSRF(跨站请求伪造) 攻击。即使在客户端使用 cookie 存储 token,cookie 也仅仅是一个存储机制而不是用于认证。另外,由于没有 session,让我们少我们不必再进行基于 session 的操作。 
  • Token 是有时效的,一段时间之后用户需要重新验证。我们也不一定需要等到token自动失效,token有撤回的操作,通过 token revocataion可以使一个特定的 token 或是一组有相同认证的 token 无效。

(3)可扩展性

  • 使用 Tokens 能够与其它应用共享权限。例如,能将一个博客帐号和自己的QQ号关联起来。当通过一个 第三方平台登录QQ时,我们可以将一个博客发到QQ平台中。
  • 使用 token,可以给第三方应用程序提供自定义的权限限制。当用户想让一个第三方应用程序访问它们的数据时,我们可以通过建立自己的API,给出具有特殊权限的tokens。

(4)多平台与跨域

  • 我们已经讨论了CORS (跨域资源共享)。当我们的应用和服务不断扩大的时候,我们可能需要通过多种不同平台或其他应用来接入我们的服务。
  • 可以让我们的API只提供数据,我们也可以从CDN提供服务(Having our API just serve data, we can also make the design choice to serve assets from a CDN.)。 在为我们的应用程序做了如下简单的配置之后,就可以消除 CORS 带来的问题。只要用户有一个通过了验证的token,数据和资源就能够在任何域上被请求到。
  • Access-Control-Allow-Origin: *

(5)基于标准

  • 有几种不同方式来创建 token。最常用的标准就是 JSON Web Tokens。很多语言都支持它。

参考文献:

  • 【JSON Web Token 入门教程】=》http://www.ruanyifeng.com/blog/2018/07/json_web_token-tutorial.html
  • 【基于Token的身份验证的原理】=》https://www.cnblogs.com/wnvalentin/articles/10816221.html
  • 【SessionID的本质】=》https://www.cnblogs.com/japanbbq/archive/2011/09/01/2161650.html
  • 1
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ChaITSimpleLove

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值