一、Cookie
1、cookie介绍
Cookie是网站为了辨别用户身份而储存在用户本地终端(Client Side)上的小型文本文件。
- 作用:Cookie主要用于保存用户登录信息、浏览记录等,以便用户再次访问时能够自动识别并提供个性化服务。
- 存储位置:Cookie数据存储在用户的浏览器本地,而不是服务器上。
- 安全性:Cookie数据存储在浏览器本地,存在被篡改或窃取的风险,因此一般需要进行加密处理。
- 大小限制:单个Cookie保存的数据大小有限制,通常不超过4KB。
2、Set-Cookie头部介绍
Set-Cookie
是一个 HTTP 响应头部,用于由服务器向客户端(如浏览器)发送,以存储用户会话信息(如登录状态、偏好设置等)。以下是一个 Set-Cookie
头部的实际例子,以及它在不同情境下的应用。
基本例子
当用户在网站上登录时,服务器可能会返回一个 Set-Cookie
头部来设置一个包含会话信息的 cookie。例如:
httpHTTP/1.1 200 OK
Content-Type: text/html
Set-Cookie: sessionid=12345; HttpOnly; Secure; Path=/; Expires=Wed, 09 Jun 2021 10:18:14 GMT
sessionid=12345
:这是 cookie 的名称(sessionid
)和值(12345
),通常用于唯一标识用户的会话。HttpOnly
:这个属性告诉浏览器不要在脚本中(如 JavaScript)暴露 cookie。这有助于减少跨站脚本攻击(XSS)的风险。Secure
:这个属性表示 cookie 仅应通过 HTTPS 连接发送,增加安全性。Path=/
:这个属性定义了 cookie 有效的路径。这里的/
表示该 cookie 对网站的所有路径都有效。Expires=Wed, 09 Jun 2021 10:18:14 GMT
:这个属性定义了 cookie 的过期时间。当浏览器的时间达到这个点时,cookie 会被自动删除。如果省略此属性,cookie 会在浏览器会话结束时过期(即,浏览器关闭时)。
多值 Cookie
Set-Cookie
头部可以在单个响应中多次出现,以设置多个不同的 cookie。例如:
httpHTTP/1.1 200 OK
Content-Type: text/html
Set-Cookie: sessionid=12345; HttpOnly; Secure; Path=/; Expires=Wed, 09 Jun 2021 10:18:14 GMT
Set-Cookie: username=JohnDoe; HttpOnly; Secure; Path=/; Max-Age=3600
在这个例子中,服务器设置了两个 cookie:一个是会话 ID,另一个是用户名。
注意:第二个 cookie 使用了 Max-Age
而不是 Expires
来指定过期时间。Max-Age
是以秒为单位的,这里设置的是 3600 秒(即 1 小时)。
删除 Cookie
要删除一个 cookie,可以通过将其过期时间设置为过去的时间来实现。由于 Expires
属性被标记为不推荐使用(deprecated),建议使用 Max-Age
并设置为 0 或负数。然而,在需要完全兼容旧浏览器的情况下,使用 Expires
设置过去的时间也是一种常见的做法。
Set-Cookie: sessionid=; Path=/; Expires=Thu, 01 Jan 1970 00:00:00 GMT
这个例子通过设置一个过去的日期来“过期”sessionid
cookie,实际上会使其被浏览器删除。注意这里 sessionid
的值被设置为空字符串,但这不是必须的;重要的是过期时间。
总之,Set-Cookie
头部是一个强大的工具,用于在服务器和客户端之间安全地交换和存储会话信息。
二、Session
1、Session介绍
Session(会话控制)在计算机中,尤其是在网络应用中,是一种用于存储特定用户会话所需的属性及配置信息的技术。它允许用户在Web应用的多个页面之间跳转时,保持其状态和数据不变。
- 作用:Session对象存储了用户会话的信息,使得用户在浏览Web应用时,不需要在每次请求时都重新输入身份认证信息,从而提高了用户体验。
- 存储位置:Session数据存储在服务器上,而不是客户端。
- 安全性:相对于存储在客户端的Cookie,Session数据在服务器上的存储更为安全,减少了数据被篡改或窃取的风险。
- 性能:随着用户数量的增加,服务器需要为每个用户维护一个Session对象,这可能会占用较多的服务器资源,影响应用性能。
2、Session鉴权
Session鉴权是一种通过在服务端保存用户的会话信息来验证用户身份的方法,它通常与Cookie配合使用。以下是一个简单的Session鉴权例子,分为前端请求和后端处理两部分进行说明。
前端请求
前端代码主要通过发送HTTP请求与后端进行交互。在登录过程中,前端会发送包含用户名和密码的POST请求到后端的登录接口。登录成功后,后端会生成一个唯一的Session ID,并将其通过HTTP响应的Set-Cookie头部发送给前端。前端收到响应后,会自动将这个Session ID存储在浏览器的Cookie中。
在后续的请求中,前端会自动在HTTP请求头中携带这个Session ID(通常是通过Cookie自动附加的),后端则根据这个Session ID来识别用户并验证其登录状态。
后端处理
后端处理主要分为以下几个步骤:
- 登录请求处理:
- 后端接收到登录请求后,会解析请求体中的用户名和密码。
- 对用户名和密码进行验证,验证成功后,生成一个唯一的Session ID。
- 将Session ID与用户的会话信息(如用户ID、登录时间等)存储在服务器端的内存或持久化存储中。
- 将Session ID通过HTTP响应的Set-Cookie头部发送给前端。
- 其他请求处理:
- 对于用户的后续请求,后端会首先检查请求头中的Cookie信息,尝试从中获取Session ID。
- 根据Session ID在服务器端的存储中查找对应的会话信息。
- 如果找到了对应的会话信息,说明用户已经登录,并且会话有效,则继续处理请求。
- 如果没有找到对应的会话信息,或者会话已经过期,则返回未授权的错误信息。
三、Token
1、Token介绍
Token(令牌)是一种在计算机系统中用于标识用户身份、授权访问权限或传递安全信息的数字签名凭证(加密字符串)。
- 作用:Token在身份验证和授权中起着重要作用,它允许服务器在无需存储用户密码等敏感信息的情况下,验证用户的身份和权限。
- 存储位置:Token通常不直接存储在服务器上,而是由服务器生成后发送给客户端(如浏览器),由客户端在后续请求中携带。
- 安全性:Token通过加密算法进行签名,确保了其不可篡改性和完整性。同时,Token可以设置过期时间,进一步提高了安全性。
- 格式:Token的格式多种多样,其中JWT(JSON Web Token)是最常用的一种。JWT由Header(头部)、Payload(有效载荷)和Signature(签名)三部分组成,各部分之间用"."分隔。
2、Token字符串
Token加密通常指的是生成一个包含加密或签名信息的字符串,这个字符串用于在客户端和服务器之间安全地传递数据。在JWT(JSON Web Tokens)的上下文中,Token是通过签名而非传统意义上的“加密”来确保数据的安全性和完整性的。签名使用了一个密钥(Secret Key或Private Key),并且只能由持有相应密钥的实体验证。
不过,为了给你一个“加密字符串”的直观感受,我可以展示一个JWT Token的示例,它看起来像是一个加密的字符串,但实际上是通过签名来保证安全性的。
以下是一个JWT Token的示例字符串:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
这个Token由三部分组成,每部分之间用点(.
)分隔:
-
Header(头部):这部分包含了Token的元数据,比如使用的令牌类型、签名算法(在这个例子中是HS256)。它本身是一个JSON对象,被编码成Base64字符串。
typ:令牌的类型,JWT令牌统一写为JWT。 alg:使用的哈希算法,如HS256、RS256或ES256等。
-
Payload(载荷):这部分包含了实际要传递的数据,比如用户ID、用户名、签发时间等。同样,它也是一个JSON对象,被编码成Base64字符串。
sub: 是JWT所面向的用户标识符。 name: 是用户的名字。 iat: 表示JWT的签发时间,是一个UNIX时间戳。
-
Signature(签名):这部分是对Header和Payload进行签名后的结果,用于验证Token的真实性和完整性。签名是使用Header中指定的算法和密钥对Header和Payload的Base64编码值进行加密(实际上是签名,不是传统意义上的加密)得到的。
SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
注意:这里的“加密”实际上是一个误导性的说法。在JWT中,数据是通过签名而不是加密来保护的。且签名是单向的,所以无法从签名"解密"出原始数据。签名确保了Token在传输过程中没有被篡改,并且只能由持有相应密钥的实体验证其有效性。
四、Session、Cookie、Token比较
Session | Cookie | Token | |
---|---|---|---|
存储位置 | 服务器端 | 客户端(浏览器) | 客户端(浏览器),但不直接存储在服务器上 |
安全性 | 较高,数据存储在服务器上 | 较低,数据存储在浏览器本地,存在被篡改的风险 | 较高,通过加密算法进行签名,确保了不可篡改性和完整性 |
性能影响 | 随着用户数量增加,可能占用较多服务器资源 | 对服务器性能影响较小 | 对服务器性能影响较小,但需要客户端在每次请求时携带Token |
有效期 | 可以设置会话超时时间 | 可以设置Cookie的有效期 | Token可以设置过期时间,过期后需要重新获取 |
跨域性 | 不可跨域,与特定域名绑定 | 不可跨域,与特定域名绑定 | 可以跨域,但需要在服务端进行验证 |
应用场景 | 适合需要保存用户会话状态的场景 | 适合需要保存用户登录状态、浏览记录等信息的场景 | 适合需要身份验证和授权的场景 |
五、维持用户的登录状态信息
维持用户的登录状态信息是互联网应用程序中的一个核心功能,它确保了用户在登录后能够持续享受应用程序提供的各项服务,而无需在每次请求时都重新进行身份验证。这一过程经历了从简单的会话管理到更复杂的令牌(Token)机制的发展。以下是对这一发展过程及主要方法的详细阐述:
1、发展过程
- 会话管理(Session Management):
- 早期应用:会话管理是维持登录状态的传统方法。在用户登录时,服务器会生成一个唯一的会话标识符(SessionID),并将其发送给客户端(通常存储在Cookie中)。客户端在后续请求中携带这个SessionID,服务器通过验证SID来确认用户的登录状态。
- 优缺点:会话管理的优点是简单易实现,不需要在客户端存储敏感信息。然而,它也存在一些缺点,如需要服务器存储大量会话信息,增加了服务器的负担;同时,会话ID的安全性也需要得到保障,以防止会话劫持等攻击。
- 令牌机制(Token-Based Authentication):
- 兴起:随着Web技术的发展和分布式系统的普及,令牌机制逐渐成为维持登录状态的主流方法。特别是JSON Web Token(JWT)等标准的出现,为令牌机制提供了更加安全、灵活的实现方式。
- 原理:用户登录时,服务器验证用户凭证后生成一个令牌(Token),并将其发送给客户端。这个令牌包含了用户的身份信息、过期时间等必要信息,并且经过加密处理以确保安全。客户端在后续请求中携带这个令牌,服务器通过验证令牌的有效性来判断用户的登录状态。
- 优缺点:令牌机制的优点在于无需服务器存储会话信息,减轻了服务器的负担;同时,令牌本身包含了用户信息,减少了数据库的访问次数。然而,令牌的安全性也是需要考虑的问题,特别是防止令牌被截获和篡改。
2、主要方法
- 会话管理:
- 实现流程:
- 用户提交登录请求。
- 服务器验证用户凭证。
- 服务器生成SessionID并存储于服务器端。
- 服务器将SessionID发送给客户端并存储在Cookie中。
- 客户端后续请求携带Cookie中的SessionID。
- 服务器验证SID以确认用户登录状态。
- 实现流程:
- 令牌机制(以JWT为例):
- 实现流程:
- 用户提交登录请求。
- 服务器验证用户凭证。
- 服务器生成JWT并发送给客户端。
- 客户端将JWT存储在Cookie、LocalStorage或sessionStorage中。
- 客户端后续请求携带JWT(通常放在请求头中)。
- 服务器验证JWT以确认用户登录状态。
- 实现流程:
总结
维持用户的登录状态信息经历了从会话管理到令牌机制的发展过程。会话管理虽然简单易用,但存在服务器负担重、安全性问题等缺点;而令牌机制则以其无需服务器存储会话信息、减少数据库访问次数等优点逐渐成为主流。在实际应用中,开发者可以根据具体需求选择合适的方法来实现用户登录状态的维持。