标题
- 一、Cookie
- 二、Session
- 三、Token
- 四、JWT
- SSO(单点登录)
- 五、OAuth2
- 如何设计权限系统
- 区别总结
Cookie、Token、Session 和 JWT 都是在 Web 开发中常用的身份验证和授权技术,它们各有优缺点,适用于不同的场景。
Cookie 简单易用,但安全性较低;
Session 相对安全,但在分布式环境下存在问题;
Token 和 JWT 实现了无状态的身份验证,具有较好的安全性和可扩展性,但需要合理管理有效期和存储敏感信息的风险。
一、Cookie
Cookie 是存储在用户浏览器中的一小段数据。当用户访问一个网站时,服务器可以在响应中设置 Cookie,浏览器会将其保存下来。在后续的请求中,浏览器会自动将 Cookie 发送给服务器,服务器可以通过读取 Cookie 来识别用户身份或存储一些特定的用户信息。
优点:
- 简单易用:Cookie 是一种被广泛支持的技术,大多数浏览器都对其有良好的支持。
- 可以存储少量的用户信息:例如用户的登录状态、偏好设置等。
缺点:
-
由于Http请求在Cookie是明文传递的,所以存在安全问题(除非是Https基于TLS/SSL进行加密);
-
安全性较低:Cookie 存储在用户的浏览器中,容易被篡改或窃取。
- 容易受到XSS和CSRF攻击。
- 需要在客户端存储,可能被用户或恶意软件篡改。
-
存储容量有限:通常只能存储几 KB 的数据。(有大小限制(通常为4KB)。)
-
受浏览器限制:一些用户可能会禁用 Cookie,这会影响网站的正常功能。
-
Cookie会被附加在后续每个Http请求中,无形中增加了流量;
-
cookie是不可以跨域的:每个cookie都会绑定单一的域名,无法在别的域名下获取使用,一级域名和二级域名之间是允许共享使用的(依靠的是domain)。
使用场景:
适用于需要持久化用户会话的场景,如在线购物车或用户偏好设置。
由于cookie存储在浏览器端,导致cookie是不够安全的,后面就诞生了session。
session是依赖于cookie的,session会把key通过cookie传送给浏览器,浏览器再次发起请求时会携带session ID
二、Session
Session 是服务器端用于存储用户会话信息的一种机制。当用户登录成功后,服务器会创建一个 Session,并为其分配一个唯一的 Session ID。这个 Session ID 通常会存储在 Cookie 中,或者通过 URL 参数传递给客户端。在后续的请求中,客户端会将 Session ID 发送给服务器,服务器通过 Session ID 来查找对应的 Session,从而获取用户的会话信息。
优点:
- 相对安全:Session 信息存储在服务器端,不容易被篡改或窃取。
- 可以存储较多的用户信息:相比 Cookie,Session 可以存储更多的数据。
缺点:
- 服务器资源消耗:每个用户的 Session 都需要占用服务器的内存资源,当用户数量较多时,可能 会对服务器性能造成一定的影响。
- 分布式环境下的问题:在分布式系统中,需要考虑 Session 的同步和共享问题,增加了系统的复杂性。
- 因为依赖cookie,依然存在安全性问题
session 认证流程:
用户第一次请求服务器的时候,服务器根据用户提交的相关信息,创建对应的 Session
请求返回时将此 Session 的唯一标识信息 SessionID 返回给浏览器
浏览器接收到服务器返回的 SessionID 信息后,会将此信息存入到 Cookie 中,同时 Cookie 记录此 SessionID 属于哪个域名
当用户第二次访问服务器的时候,请求会自动判断此域名下是否存在 Cookie 信息,如果存在自动将 Cookie 信息也发送给服务端,服务端会从 Cookie 中获取 SessionID,再根据 SessionID 查找对应的 Session 信息,如果没有找到说明用户没有登录或者登录失效,如果找到 Session 证明用户已经登录可执行后面操作。
根据以上流程可知,SessionID 是连接 Cookie 和 Session 的一道桥梁,大部分系统也是根据此原理来验证用户登录状态。
使用场景:
适用于需要存储大量用户数据的Web应用程序,如在线游戏或复杂的企业管理系统。
三、Token
Token 是一种基于令牌的身份验证机制。当用户登录成功后,服务器会生成一个 Token,并将其返回给客户端。客户端在后续的请求中,将 Token 包含在请求头或请求参数中发送给服务器,服务器通过验证 Token 的有效性来识别用户身份。
优点:
- 无状态:Token 本身包含了用户的身份信息,服务器不需要存储 Session,因此可以轻松地实现水平扩展。(服务端无状态化、可扩展性好)
- 安全性较高:Token 可以使用加密算法进行签名,确保其不被篡改。
- 跨平台、跨设备:Token 可以在不同的平台和设备上使用,方便用户在多个设备上访问应用。(支持移动端设备)
- 支持跨程序调用
token 的身份验证流程:
- 客户端使用用户名跟密码请求登录
- 服务端收到请求,去验证用户名与密码
- 验证成功后,服务端会签发一个 token 并把这个 token 发送给客户端
- 客户端收到 token 以后,会把它存储起来,比如放在 cookie 里或者 localStorage 里
- 客户端每次向服务端请求资源的时候需要带着服务端签发的 token
- 服务端收到请求,然后去验证客户端请求里面带着的 token ,如果验证成功,就向客户端返回请求的数据
- 每一次请求都需要携带 token,需要把 token 放到 HTTP 的 Header 里
- 基于 token 的用户认证是一种服务端无状态的认证方式,服务端不用存放 token 数据。用解析 token 的计算时间换取 session 的存储空间,从而减轻服务器的压力,减少频繁的查询数据库
- token 完全由应用管理,所以它可以避开同源策略
缺点:
- 存储和传输开销:Token 通常比 Cookie 或 Session ID 更大,会增加网络传输的开销。
- 有效期管理:需要合理设置 Token 的有效期,过期后需要用户重新登录。
使用场景:
- 适用于RESTful API和单页应用程序(SPA),其中状态不需要存储在服务器上。
四、JWT
JWT 是一种基于 JSON 的开放标准(RFC 7519),用于在网络应用环境间传递声明。它由三部分组成:头部(Header)、载荷(Payload)和签名(Signature)。头部和载荷部分都是 JSON 对象,签名是使用特定的算法对头部和载荷进行签名得到的。
优点:
- 自包含:JWT 本身包含了用户的身份信息,不需要服务器存储 Session,实现了无状态的身份验证。
- 可扩展性强:可以在载荷中添加自定义的声明,满足不同应用的需求。
- 跨域支持:由于 JWT 是基于标准的 JSON 格式,可以轻松地在不同的域之间传递。
缺点:
- 一旦签发,无法撤销:如果 JWT 被泄露,在有效期内无法撤销,只能等待其过期。
- 存储敏感信息的风险:如果在 JWT 的载荷中存储了敏感信息,可能会存在安全风险。
使用场景:
- 适用于需要跨域认证的微服务架构,或需要在客户端和服务器之间安全传输大量数据的场景。
SSO(单点登录)
-
定义
SSO 是一种身份验证机制,允许用户使用一组凭据(如用户名和密码)登录到多个相关但独立的应用程序或系统中。用户只需进行一次身份验证,后续访问其他关联应用时无需再次输入凭据。 -
工作原理
通常有一个中央身份验证服务器(CAS - Central Authentication Server)。当用户尝试访问应用 A 时,应用 A 将用户重定向到 CAS。用户在 CAS 进行登录认证后,CAS 会生成一个票据(Ticket),并将用户重定向回应用 A,同时将票据传递给应用 A。应用 A 拿着票据到 CAS 验证,验证通过后允许用户访问。当用户再访问应用 B 时,应用 B 发现用户未登录,同样将用户重定向到 CAS,CAS 发现用户已经登录过了(通过之前在用户浏览器中设置的 Cookie 等机制),就直接给应用 B 生成票据,应用 B 验证票据后允许用户访问。 -
应用场景
在企业内部多个相关系统中应用广泛。例如,一家公司有内部的办公系统、邮件系统、项目管理系统等,使用 SSO 可以让员工只登录一次,就能访问这些系统,提高工作效率,减少用户记忆多个账号密码的负担。 -
优缺点
优点:
1.用户体验好,只需一次登录。
2.便于集中管理用户账号和权限,企业的 IT 部门可以在中央服务器上统一管理用户的身份和访问权限。
缺点:
1.对中央身份验证服务器的依赖度高,如果 CAS 出现故障,可能会影响所有关联应用的访问。
2.安全性方面,一旦中央服务器被攻破,可能导致所有相关系统的安全风险。
五、OAuth2
是一个行业标准授权协议,主要用来授权第三方应用获取有限的权限,它的最终目标是为第三方应用颁发一个有时效性的令牌token,使得第三方应用能够通过该令牌获取相关资源(比如第三方登录)
官方解释
OAuth(开放授权)是一个开放标准,允许用户让第三方应用(网站/app)访问该用户在另一网站
(qq, 微博,微信等等)上存储的私密的资源(如照片,视频,联系人列表),
而无需将用户名和密码提供给第三方应用。
4种模式
工作原理
主要涉及以下角色:
资源所有者(Resource Owner):通常是用户,拥有要被访问的资源(如用户在某个网站上的照片、联系人等)。
客户端(Client):即第三方应用程序,想要访问资源所有者的资源。
授权服务器(Authorization Server):负责对客户端进行授权,验证客户端的身份,并颁发访问令牌。
资源服务器(Resource Server):存储资源所有者的资源,在接收到客户端的访问请求并验证令牌后,提供相应的资源。
典型流程如下:
客户端请求资源所有者的授权,资源所有者同意后,客户端从授权服务器获取授权码(Authorization Code)。
客户端拿着授权码向授权服务器换取访问令牌(Access Token)。
客户端使用访问令牌向资源服务器请求资源,资源服务器验证令牌后提供资源。
应用场景
在互联网应用中大量使用。例如,用户可以使用微信账号登录第三方应用(如某新闻客户端),第三方应用通过 OAuth 2.0 从微信获取用户的基本信息(如头像、昵称等)来为用户创建账号,而微信不会将用户的密码透露给第三方应用。
优缺点
- 优点:
安全性高,不暴露用户的登录凭据给第三方应用,保护了用户隐私。
灵活性强,可实现不同应用间的资源共享和授权访问,适用于开放的互联网环境。 - 缺点:
实现相对复杂,涉及多个角色和交互流程,开发成本较高。
如果配置不当,可能会出现安全漏洞,例如授权码泄露可能导致非法获取访问令牌。
如何设计权限系统
首先有基本的4张表,用户表、角色表、菜单表、资源表
他们之间关系多对多,因此需要中间表作为关联
至少的需要 用户角色关系表、角色菜单关系表、菜单资源关系表
最好再来个日记记录表,非必须
区别总结
Cookie 和 Session 的区别
-
安全性:Session 比 Cookie 安全,Session 是存储在服务器端的,Cookie 是存储在客户端的。
-
存取值的类型不同:Cookie 只支持存字符串数据,想要设置其他类型的数据,需要将其转换成字符串,Session 可以存任意数据类型。
-
有效期不同:Cookie 可设置为长时间保持,比如我们经常使用的默认登录功能,Session 一般失效时间较短,客户端关闭(默认情况下)或者 Session 超时都会失效。
-
存储大小不同:单个 Cookie 保存的数据不能超过 4K,Session 可存储数据远高于 Cookie,但是当访问量过多,会占用过多的服务器资源。
Token 和 Session 的区别
-
Session 是一种记录服务器和客户端会话状态的机制,使服务端有状态化,可以记录会话信息。而 Token 是令牌,访问资源接口(API)时所需要的资源凭证。Token 使服务端无状态化,不会存储会话信息。
-
Session 和 Token 并不矛盾,作为身份认证 Token 安全性比 Session 好,因为每一个请求都有签名还能防止监听以及重放攻击,而 Session 就必须依赖链路层来保障通讯安全了。如果你需要实现有状态的会话,仍然可以增加 Session 来在服务器端保存一些状态。
-
所谓 Session 认证只是简单的把 User 信息存储到 Session 里,因为 SessionID 的不可预测性,暂且认为是安全的。而 Token ,如果指的是 OAuth Token 或类似的机制的话,提供的是 认证 和 授权 ,认证是针对用户,授权是针对 App 。其目的是让某 App 有权利访问某用户的信息。这里的 Token 是唯一的。不可以转移到其它 App上,也不可以转到其它用户上。Session 只提供一种简单的认证,即只要有此 SessionID ,即认为有此 User 的全部权利。是需要严格保密的,这个数据应该只保存在站方,不应该共享给其它网站或者第三方 App。所以简单来说:如果你的用户数据可能需要和第三方共享,或者允许第三方调用 API 接口,用 Token 。如果永远只是自己的网站,自己的 App,用什么就无所谓了。
-
一、存储位置
Session
服务器端存储:Session 数据通常存储在服务器端。当用户登录成功后,服务器会创建一个 Session 对象,并为其分配一个唯一的标识符(Session ID)。这个 Session ID 会被发送到客户端,通常是通过 Cookie 存储在客户端浏览器中。
示例:在一个使用 PHP 开发的网站中,当用户登录时,服务器会在内存或数据库中创建一个 Session 数据结构,用于存储用户的登录状态、权限等信息。
Token
客户端存储:Token 通常存储在客户端。在用户认证成功后,服务器会生成一个 Token 并将其发送给客户端。客户端可以将 Token 存储在本地存储(如 Local Storage、Session Storage)或 Cookie 中。
示例:在一个基于 JavaScript 的单页应用(SPA)中,用户登录后,服务器返回的 JWT(JSON Web Token)会被存储在浏览器的 Local Storage 中,供后续的 API 请求使用。 -
二、数据结构
Session
数据格式多样:Session 数据可以是各种格式,取决于服务器端的实现。它可以是简单的键值对、复杂的对象或序列化的数据。
示例:在一个使用 Node.js 和 Express 框架的应用中,Session 数据可能是一个包含用户 ID、用户名、登录时间等属性的 JavaScript 对象。
Token
标准化格式:Token 通常有特定的格式,如 JWT(JSON Web Token)是一种流行的 Token 格式,它由三部分组成:头部(Header)、载荷(Payload)和签名(Signature)。
示例:一个 JWT Token 可能如下所示:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
其中第一部分是头部(Base64 编码),第二部分是载荷(Base64 编码),第三部分是签名。 -
三、安全性
Session
依赖于 Session ID 的保护:由于 Session 数据存储在服务器端,其安全性主要依赖于对 Session ID 的保护。如果 Session ID 被窃取,攻击者可能会获取用户的 Session 数据,从而冒充用户身份。
示例:如果用户的浏览器存在跨站脚本攻击(XSS)漏洞,攻击者可能获取到存储在 Cookie 中的 Session ID,进而劫持用户的 Session。
Token
基于签名机制:Token 的安全性依赖于其签名机制。例如,JWT Token 使用私钥进行签名,在验证时,服务器使用公钥来验证签名的有效性。如果 Token 被篡改,签名验证将失败。
示例:在一个基于微服务架构的系统中,各个服务使用公钥验证从客户端传来的 JWT Token 的签名,确保 Token 没有被篡改。 -
四、扩展性
Session
服务器负载问题:在分布式系统或高负载场景下,Session 的管理会变得复杂。因为 Session 数据存储在服务器端,当用户请求在多个服务器之间负载均衡时,需要解决 Session 共享的问题,如使用分布式缓存(如 Redis)来存储 Session 数据。
示例:在一个大型的电商网站中,如果有多台 Web 服务器处理用户请求,为了确保用户的 Session 数据在这些服务器之间的一致性,需要采用专门的 Session 共享解决方案。
Token
无状态性利于扩展:Token 是无状态的,服务器不需要存储 Token 的相关数据。每个请求携带 Token,服务器只需要验证 Token 的有效性即可。这使得在分布式系统和微服务架构中,Token 更易于扩展和处理。
示例:在一个由多个微服务组成的系统中,每个微服务只需要验证传入请求中的 JWT Token,而不需要与其他服务共享用户状态信息,便于系统的水平扩展。 -
五、有效期管理
Session
服务器端控制:Session 的有效期通常由服务器端控制。可以设置一个固定的过期时间,或者根据用户的活动情况(如一段时间内没有操作)来决定 Session 是否过期。
示例:在一个网站中,可以设置 Session 的过期时间为 30 分钟,即用户登录后 30 分钟内没有操作,Session 就会自动失效。
Token
内置有效期或自定义控制:Token 本身可以内置有效期信息。例如,JWT Token 的载荷中可以包含一个exp(expiration time)字段来表示 Token 的过期时间。此外,也可以在应用层自定义 Token 的有效期管理机制。
示例:一个 JWT Token 的载荷中可能有"exp": 1672531200,表示这个 Token 在 2023 年 1 月 1 日 00:00:00 过期。
Token 和 JWT 的区别
相同:
-
都是访问资源的令牌
-
都可以记录用户的信息
-
都是使服务端无状态化
-
都是只有验证成功后,客户端才能访问服务端上受保护的资源
区别:
-
Token:服务端验证客户端发送过来的 Token 时,还需要查询数据库获取用户信息,然后验证 Token 是否有效。
-
JWT:将 Token 和 Payload (载荷)加密后存储于客户端,服务端只需要使用密钥解密进行校验(校验也是 JWT 自己实现的)即可,不需要查询或者减少查询数据库,因为 JWT 自包含了用户信息和加密的数据
-
定义
Token(令牌):是一种用于身份验证和授权的机制。它是一个代表用户身份或权限的字符串。Token 可以由服务器生成并发送给客户端,客户端在后续的请求中携带这个 Token 来证明自己的身份或权限。Token 的格式和生成方式可以多种多样,没有固定的标准格式。
JWT(JSON Web Token):是一种特定格式的 Token。它遵循 RFC 7519 标准,由三部分组成:头部(Header)、载荷(Payload)和签名(Signature)。这三部分用点(.)分隔并连接成一个字符串。 -
结构
Token:
结构不固定,可能只是一个简单的随机字符串,比如一个由服务器随机生成的 32 位十六进制字符串,如"a3b9c4d7e2f8g1h6i9j4k7l2m5n8o3p9"。
也可能是具有一定格式但较为简单的字符串,例如包含用户 ID 和时间戳的字符串:“user123_1672531200”,其中user123是用户 ID,1672531200是时间戳。
JWT:
头部(Header):是一个 JSON 对象,通常包含令牌的类型(如"typ":“JWT”)和所使用的签名算法(如"alg":“HS256”),经过 Base64 编码后得到第一部分。
载荷(Payload):也是一个 JSON 对象,包含了一些声明(Claims),如用户身份信息(sub字段表示主题,即用户 ID)、过期时间(exp字段)、签发时间(iat字段)等,经过 Base64 编码后得到第二部分。
签名(Signature):是对头部和载荷使用指定的签名算法和密钥进行签名得到的结果,用于验证令牌的真实性和完整性,是第三部分。例如,一个 JWT 可能看起来像"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c"。 -
生成与验证
Token:
生成方式较为灵活。例如,服务器可以使用随机数生成器生成一个随机字符串作为 Token,或者基于用户的某些信息(如用户名和密码的哈希值)通过某种算法生成 Token。
验证时,服务器通常需要在数据库或缓存中存储与 Token 相关的信息。例如,当客户端携带 Token 请求时,服务器要查找数据库中存储的对应 Token 记录来验证其有效性。
JWT:
生成需要按照标准的流程。首先构建头部和载荷的 JSON 对象,然后进行 Base64 编码,最后使用签名算法和密钥生成签名。
验证时,服务器接收 JWT,先将其拆分为头部、载荷和签名三部分。对头部和载荷重新计算签名并与接收到的签名进行比较,如果一致且载荷中的声明(如过期时间)有效,则认为 JWT 有效,无需查询数据库(无状态性),除非有额外的数据需求(如查询用户权限的详细信息)。 -
应用场景
Token:
适用于简单的身份验证场景,尤其是在小型应用或对安全性要求不是极高的场景中。例如,一个公司内部的简单考勤系统,可能只使用简单的 Token 来识别员工身份,Token 可能只是基于员工工号生成的一个简单字符串。
JWT:
广泛应用于分布式系统、微服务架构和跨域身份验证等场景。例如,在一个由多个微服务组成的电商系统中,用户登录后,认证服务生成 JWT 并发送给客户端,客户端在访问订单服务、商品服务等其他微服务时,携带 JWT 进行身份验证,各个微服务可以独立地验证 JWT 的有效性,方便快捷且安全。
总的来说,JWT 是一种标准化、结构化的 Token,具有安全性高、无状态等优点,适用于复杂的网络架构;而 Token 是一个更宽泛的概念,其实现方式更加灵活多样。
SSO 跟OAuth 2.0区别
- 目的
SSO 主要解决用户在多个相关应用中的重复登录问题,侧重于身份验证的统一。
OAuth 2.0 侧重于授权,即让第三方应用在用户授权的前提下获取特定的资源,不涉及用户在第三方应用中的身份验证(第三方应用可能通过其他方式验证用户身份,但 OAuth 2.0 本身不处理)。 - 涉及角色
SSO 通常涉及用户和中央身份验证服务器以及多个应用程序。
OAuth 2.0 涉及资源所有者、客户端、授权服务器和资源服务器等多个角色。 - 安全机制
SSO 依赖于中央服务器对用户身份的验证和票据的安全传递。
OAuth 2.0 通过授权码、访问令牌等机制来保障资源访问的安全性,重点在授权流程的安全。 - 应用场景
SSO 适用于企业内部或相互关联紧密的系统之间。
OAuth 2.0 适用于开放的互联网环境,用于第三方应用获取用户资源的授权。