文章目录

  • 前言
  • Cookie
  • Session
  • sessionId
  • Data
  • 优缺点
  • Token
  • Header
  • Playload
  • signature
  • 拓展
  • 总结


前言

之前准备面试的时候就学过这些有什么区别与联系,但一直是一知半解,后面面试阿里的时候,遇到了这个问题,被追根问底到不会,所以这次来总结一下。

Cookie

首先来说最容易理解的cookie,cookie就是在你访问某个网页之后,对方在你本地浏览器中以键值对的形式添加了一些数据,下次再访问时就会携带这些信息,这也是我们重新访问该网页不用重新登陆的基础。

Session

session可以理解为会话。最常见的一句话就是session存储在服务器,token存储在客户端。那么session是以什么形式存在服务器的呢,session的主要作用又是啥呢。

可以简单的把session理解为一个对象,主要包含两个内容,

  • sessionId
  • Data

sessionId

其中每一个sessionId是为了标识每一个不同的session,也就是标识每一个访问用户。

举例来说,当我们访问某个服务时,服务器会先检查我们请求的参数中是否携带sessionId,如果没有的话说明是一个新用户,这时会新建一个session对象,在处理完响应的请求后,会把该session对象的sessionId返回给客户端,客户端拿到这个sessionId存储至cookie中,下次再访问时携带sessionId,服务器就可以识别我们是否已经登录过。

Data

在一个用户访问我们我们时,我们可以根据其sessionId获取到相应的session对象,然后向session对象中添加或者查询数据。

例如,在用户第一次访问我们的时候,假如用户名密码正确,我们新建了一个session对象,然后把用户的实体类对象存入到session中,下次用户再来访问时,我们会先试图从session中获取用户信息,假如存在的话,就继续后续操作,假如不存在,说明用户未登录,则跳转到登录界面。

其中数据在session中存储是以键值对的形式存在,一般key为String,value为Object。

优缺点

session中的数据一般保留在内存中(也可以持久化到数据库或文本文件中),而且根据sessionId查询速度很快。

但是当有大量用户同时在线时,例如几十万用户同时在线,则有可能会造成内存拉满。

还有一种情况是,假如服务端有多台服务器做了负载均衡,假如你本次登录请求时分发给了A服务器,那么下次请求有可能会发给B服务器,那么B服务器中没有存储你的登录态,所以有可能需要重新登录。解决方式是A服务器与B服务器同步复制session,或者将session存储至同一数据库内统一读写,不过运维成本会较高。

java token缓存最高支持多久 java中token,cookie与session_服务端

Token

从上面的流程中,我们可以理解Session是存在服务器的,那么Token又是如何存在客户端能完成用户标识呢。

Token一般的鉴权流程为

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

整个流程比较简单,今天主要解释服务端生成token以及验证token的过程。

先来看一下什么是Token,本质上来说其实就是一串字符串,一般存在于一次请求的header或cookie中

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjhEbkpBTGF6M1VsbERwQkp0cVN3IiwiaWF0IjoxNjQ4NjA5MDU1LCJleHAiOjE2NDkyMTM4NTV9.lWkB6H9F1MbTDWdZaIJlmq8_t3QoG-wEkD0JdFBk6PA

//按小数点可以分为三个部分
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.
eyJpZCI6IjhEbkpBTGF6M1VsbERwQkp0cVN3IiwiaWF0IjoxNjQ4NjA5MDU1LCJleHAiOjE2NDkyMTM4NTV9.
lWkB6H9F1MbTDWdZaIJlmq8_t3QoG-wEkD0JdFBk6PA

Header

其中第一部分称为header,用Base64解码后得到以下信息:

{"alg":"HS256","typ":"JWT"}

可以看到其实就是一个json对象,主要包含了加密方式(称之为摘要更为准确)与token类型,这里就是sha256与jwt。

同理,服务端在制作Token时会将这些信息例如使用什么加密方式,用Base64编码作为header

{"alg":"HS256","typ":"JWT"}
//Base64编码
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9

Playload

第二部分称为playload,用Base64解码后得到以下信息:

{"id":"8DnJALaz3UllDpBJtqSw","iat":1648609055,"exp":1649213855}

这里主要包含了用户信息、创建时间、过期时间

这些字段名称不强制使用,但一般推荐为以下字段。

  • iss: jwt签发者
  • sub: jwt所面向的用户
  • aud: 接收jwt的一方
  • exp: jwt的过期时间,这个过期时间必须要大于签发时间
  • nbf: 定义在什么时间之前,该jwt都是不可用的.
  • iat: jwt的签发时间
  • jti: jwt的唯一身份标识,主要用来作为一次性token,从而回避重放攻击。

因为使用Base64编码等同于明文,所以这里不建议存储敏感信息,用户身份等,所以一般只存储用户ID或用户对应的uuid即可,服务端根据用户ID或uuid去缓存中获取完整的用户信息。

那么服务器怎么知道我们是否的信息是否是伪造的呢,就是通过第三部分,信息摘要。

signature

第三部分主要由前两个部分数据通过字符串连接经过密钥根据加密算法获取摘要而成,目的是为了验证上述部分数据是否被篡改以及是否是服务端所签发的。

// javascript
var encodedString = base64UrlEncode(header) + '.' + base64UrlEncode(payload);

// 其中'secret'为服务端自定义的密钥,因此服务端应保管好该数据。
var signature = HMACSHA256(encodedString, 'secret'); 
//lWkB6H9F1MbTDWdZaIJlmq8_t3QoG-wEkD0JdFBk6PA

有了以上三部分数据之后,就可以拼装成我们想要的token字符串作为鉴权使用。

java token缓存最高支持多久 java中token,cookie与session_网络安全_02

拓展

  1. Token如何解决CSRF攻击
  2. Oauth2相关知识

总结

session与token都有各自的优缺点,一句话来说就是

session用空间换时间,token用时间换空间。

一般来说,前后端分离项目使用token较多,前后端不分离项目使用session较多,具体使用那种形式,需要根据实际需求来考虑。