cookie 认证、session 认证和 token 认证

2,265 阅读4分钟

HTTP 协议本身是去状态的,需要浏览器以及客户端解决这种问题,出现了这三种技术用于解决该问题

1. cookie 认证

  • 是服务端向客户端发送的一段数据,用于验证某一个会话。
  • 不同网站的 cookie 字段由服务器端设置,通常放入 session-id 或者 token 值来验证会话的登录状态。
  • 信息明文存在于客户端
  • 信息大有限制问题

分类

  • session cookie:

    • key-value 形式,
    • 当我们用浏览器访问服务端时,服务器返回一个 session cookie,当访问该网站其他页面时,我们用该 coolie 来验证身份;重启服务器后下次重新访问该页面时,需要重新获取;
    • 一般情况下,访问一个网站,cookie 不会变化,
  • permenent cookie:

    • 包括:名字、值、过期时间和路径等
    • 第一次用浏览器访问服务端时,服务端生成 permenent cookie 发送给 UA,后者将其保存到某个目录下;
    • 当下一次请求同一网站时,将该 cookie 发送给服务端

2. session 认证

  • 保存在服务器端的经过加密的数据,用于存储用户特定会话所需的属性以及配置信息的数据
  • 客户端发起请求,服务器生成并返回 sessionID,可以设置有效时间,即使浏览器没有关闭,也会失效。
  • 当用户在应用程序的web 间页面跳转时,session id 不变
  • 客户端向服务端:cookie
  • 服务端向客户端:request.session -缺点:响应慢和集群问题(nginx:代理服务器之间分配资源)

2.1 session 安全机制

  • 设置了时效性,
  • 浏览器关闭,session 失效
  • 当用户的 ip、ua 等信息变化后,session 失效

3 token 认证

  • token 是服务端向客户端生成的用于验证用户登录状态的加密数据
  • 与 session 比起来, token 进行验证签名,在发送给浏览器
  • 存在秘钥,其申城和验证 token 的算法是一种

3.1 token 认证的流程

  1. 客户端第一次发送请求(用户名和密码)
  2. 登录成功后,服务器将登录凭证做数字签名,加密后得到 token 值返回给客户端
  3. 客户端后续请求,将受到的 token 值放到数据包的 cookie 中,发送给服务器
  4. 服务器提取客户端的 token值,做解密操作和签名认证后,拿到其中的登录凭证,判断其有效性

jwt 认证

即 json web token 认证。

Json web token (JWT), 是为了在网络应用环境间传递声明而执行的一种基于JSON的开放标准((RFC 7519).该token被设计为紧凑且安全的,特别适用于分布式站点的单点登录(SSO)场景。JWT的声明一般被用来在身份提供者和服务提供者间传递被认证的用户身份信息,以便于从资源服务器获取资源,也可以增加一些额外的其它业务逻辑所必须的声明信息,该token也可直接被用于认证,也可被加密。

在用户注册或登录后,我们想记录用户的登录状态,或者为用户创建身份认证的凭证。我们不再使用Session认证机制,而使用Json Web Token认证机制。

jwt 认证的构成

1. eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.
2. eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.
3. TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ

• 头部(header)

  • 声明类型:gwt
  • 声明签证算法:HS256
  • 且被加密过:base64 算法(可解密)
{
  'typ': 'JWT',
  'alg': 'HS256'
}

• 载荷(payload)

  • 存放有效信息,包含以下三部分
  • 标准声明:iss(jwt 签发者)、sub(jwt 所面向的用户)、aud(接收 jwt 的一方)、exp(jwt 过期时间,必须大于签发时间)nbf(定于在什么时间之前,该 jwt 不可用)、iat(jwt 的签发时间)、jti(jwt 唯一身份表示,主要用来作为一次性 token,从而回避重放攻击)
  • 公有声明:可以 添加任何信息,一般添加用户相关信息或者其他业务需要的必要信息,不建议加敏感信息,因为在客户端可解密
  • 私有声明:提供者和消费者共同定义的声明,一般不建议存放敏感信息,这意味着可归类于敏文信息

• 签证(signature)

  • header(base64 后的)
  • payload(base64 后的)
  • secret 秘钥(盐) 注意:secret是保存在服务器端的,jwt的签发生成也是在服务器端的,secret就是用来进行jwt的签发和jwt的验证,所以,它就是你服务端的私钥,在任何场景都不应该流露出去。一旦客户端得知这个secret, 那就意味着客户端是可以自我签发jwt了。