Skip to content

Session & Token #46

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
trayvonRen opened this issue Apr 6, 2020 · 2 comments
Open

Session & Token #46

trayvonRen opened this issue Apr 6, 2020 · 2 comments

Comments

@trayvonRen
Copy link

HTTP 协议是无状态协议,所以服务器端必须部署相关的逻辑来保持用户的认证状态。
目前主流有两种 Session 和 Token

@trayvonRen
Copy link
Author

Session

在计算机网络中, session 是一个抽象概念,开发者为了实现中断和继续等操作,将 user agentserver 之间一对一的交互,抽象为“会话”,进而衍生出“会话状态”,也就是 session 的概念。
而我们今天常说的 Session,是借助 cookie 或者其他手段实现的,一种会话状态的具体实现,最常见的就是用户登录态的维持。

实现原理

一个简单的 Session 有以下过程

  • 浏览器向服务器发送请求,携带一定的用户认证信息(用户名,密码)
  • 服务器核对用户信息,确认无误后,生成一个 session_id, 并储存在内存中。(也可储存在数据库)
  • 服务器响应浏览器请求,并设置 Set-Cookie 的值为 session_id
  • 浏览器每次发送请求会把 Cookie 带上,服务器再比对储存的 session_id 值,判断是否已经登录。

注意点

  • 服务器一般会设置一个较短的过期时间,防止客户端 Cookie 被人窃取。
  • Cookie 没有被禁用的情况下,这一切对于前端来说几乎是没有感知的,因为浏览器会自动携带 Cookie
  • 如果浏览器禁用 Cookie,可以把 session_id 放在 url 中携带,或者放在请求体中(比较麻烦)。
  • 只要 Cookie 没过期,用户登录态一直存在。

总结

安全性

如果 Cookie 被窃取了,攻击者就可以登录账号。
为了解决这个问题,可以采用以下方法

  • 设置 Cookie 有效期不要过长
  • 设置 CookieSecure 属性为 true
    标记为 SecureCookie 只应通过被 HTTPS 协议加密过的请求发送给服务端。
  • 设置 CookieHttpOnly 属性为 true
    为避免跨域脚本 (XSS) 攻击,通过 JavaScriptDocument.cookie API 无法访问带有 HttpOnly 标记的 Cookie,它们只应该发送给服务端。
  • 加密 Cookie
    万一攻击者窃取了 Cookie,经过加密的 Cookie 可以防止攻击者破解里面的用户信息。

无论如何,都不应该把敏感信息放在 Cookie 中

缺点

  • 服务器需要维护 Session 数据,如果需要单点登录,就要把 Session 写入数据库持久层,做 Session 共享。
  • Cookie 在跨域场景下表现不好。
  • 用户有可能会禁用 Cookie
  • Cookie 数量和长度的限制。每个 domain 最多只能有20条 Cookie,每个 cookie 长度不能超过4KB。

@trayvonRen
Copy link
Author

Token

基于 token 认证方式,不需要在服务端去保留用户的认证信息或者会话信息。这就意味着基于 token 认证机制的应用不需要去考虑用户在哪一台服务器登录了,这就为应用的扩展提供了便利。
流程上是这样的:

  • 用户使用用户名密码来请求服务器
  • 服务器进行验证用户的信息
  • 服务器通过验证发送给用户一个 token
  • 客户端存储 token,并在每次请求时附送上这个 token 值
  • 服务端验证 token 值,并返回数据

JSON Web Token(缩写 JWT)是 token 认证的一种具体实现。

JWT 的原理

JWT 的原理是,服务器认证以后,生成一个 JSON 对象,发回给用户,就像下面这样。

{
  "姓名": "张三",
  "角色": "管理员",
  "到期时间": "2018年7月1日0点0分"
}

以后,用户与服务端通信的时候,都要发回这个 JSON 对象。服务器完全只靠这个对象认定用户身份。为了防止用户篡改数据,服务器在生成这个对象的时候,会加上签名。
服务器就不保存任何 session 数据了,也就是说,服务器变成无状态了,从而比较容易实现扩展。

JWT 的数据结构

阮一峰: JSON Web Token 入门教程

JWT 工作流程

  • 浏览器首次向服务器发送请求,携带一定的用户信息(用户名,密码)
  • 服务器验证用户信息,如果验证通过,使用 jwt 规范生成 token
  • 浏览器以后每次请求都会携带 token

可以把它放在 Cookie 里面自动发送,但是这样不能跨域,所以更好的做法是放在 HTTP 请求的头信息 Authorization 字段里面。

Authorization: Bearer <token>
  • 服务器使用签名算法验证 token 是否被篡改过。如果没有,则解析 token 实现用户认证。

总结

  • token 和 Session + Cookie 的本质区别就服务器不保存会话状态。
  • JWT 本身包含了认证信息,一旦泄露,任何人都可以获得该令牌的所有权限。为了减少盗用,JWT 的有效期应该设置得比较短。对于一些比较重要的权限,使用时应该再次对用户进行认证。
  • 为了减少盗用,JWT 不应该使用 HTTP 协议明码传输,要使用 HTTPS 协议传输。
  • JWT 因为认证信息保存在前端,服务器不保存用户状态,单点登录比较容易实现。

参考资料

Introduction to JSON Web Tokens

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant