转自
https://blog.csdn.net/liyifan687/article/details/80077928
前言
HTTP协议是无状态的协议
。一旦数据交换完毕,客户端与服务器端的连接就会关闭,再次交换数据需要建立新的连接。这就意味着服务器无法从连接上跟踪会话。
会话
,指用户登录网站后的一系列动作,比如浏览商品添加到购物车并购买。会话(Session)跟踪
是Web程序中常用的技术,用来跟踪用户的整个会话。常用的会话跟踪技术是Cookie与Session
。Cookie通过在客户端记录信息确定用户身份
,Session通过在服务器端记录信息确定用户身份。
Cookie、session和token
登录网站,今输入用户名密码登录了,第二天再打开很多情况下就直接打开了。这个时候用到的一个机制就是cookie。
session一个场景是购物车,添加了商品之后客户端处可以知道添加了哪些商品,而服务器端如何判别呢,所以也需要存储一些信息就用到了session。
1. Cookie
-
通俗讲,是访问某些网站后
在本地存储的一些网站相关信息
,下次访问时减少一些步骤。更准确的说法是:cookie由服务器生成
,发送给浏览器
,浏览器把cookie以kv形式
保存到某个目录下的文本文件
内,并随每一个请求发送至同一服务器,是在客户端保持状态的方案。 -
Cookie的主要内容包括:
名字,值,过期时间,路径和域
。使用Fiddler抓包就可以看见,比方说我们打开百度的某个网站可以看到Headers包括Cookie,如下:BIDUPSID: 9D2194F1CB8D1E56272947F6B0E5D47E PSTM: 1472480791 BAIDUID: 3C64D3C3F1753134D13C33AFD2B38367:FG ispeed_lsm: 2 MCITY: -131: pgv_pvi: 3797581824 pgv_si: s9468756992 BDUSS: JhNXVoQmhPYTVENEdIUnQ5S05xcHZMMVY5QzFRNVh5SzZoV0xMVDR6RzV-bEJZSVFBQUFBJCQAAAAAAAAAAAEAAACteXsbYnRfY2hpbGQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALlxKVi5cSlYZj BD_HOME: 1 H_PS_PSSID: 1423_21080_17001_21454_21408_21530_21377_21525_21193_21340 BD_UPN: 123253 sug: 3 sugstore: 0 ORIGIN: 0 bdime: 0
-
key, value形式
。过期时间可设置的,如不设,则浏览器关掉就消失了,存储在内存当中,否则就按设置的时间来存储在硬盘上的,过期后自动清除,比方说开关机关闭再打开浏览器后他都会还存在,前者称之为Session cookie 又叫 transient cookie(会话cookie
),后者称之为Persistent cookie 又叫 permenent cookie(持久cookie
)。路径和域就是对应的域名,a网站的cookie自然不能给b用。
2. Session
- 存在服务器的一种用来
存放用户数据的HashTable结构
。 - 浏览器第一次发送请求时,服务器
自动生成了一个HashTable和一个Session ID
来唯一标识这个HashTable,并将其通过响应发送到浏览器
。浏览器第二次发送请求会将前一次服务器响应中的Session ID放在请求中一并发送到服务器上,服务器从请求中提取出Session ID,并和保存的所有Session ID进行对比,找到这个用户对应的HashTable。- 一般这个值会有个时间限制,超时后毁掉这个值,
默认30分钟
。
- 一般这个值会有个时间限制,超时后毁掉这个值,
- 当用户在应用程序的 Web页间跳转时,存储在 Session 对象中的变量不会丢失而是在整个用户会话中一直存在下去。
Session的实现方式和Cookie有一定关系
。建立一个连接就生成一个session id,打开几个页面就好几个了,这里就用到了Cookie,把session id存在Cookie中,每次访问的时候将Session id带过去就可以识别了。
3. token
-
Token的引入
:Token是在客户端频繁向服务端请求数据,服务端频繁的去数据库查询用户名和密码并进行对比,判断用户名和密码正确与否,并作出相应提示,在这样的背景下,Token便应运而生。 -
Token的定义
:Token是服务端生成
的一串字符串
,以作客户端进行请求的一个令牌
,当第一次登录后
,服务器生成一个Token
便将此Token返回给客户端
,以后客户端只需带上这个Token前来请求数据即可
,无需再次带上用户名和密码。最简单的token组成: uid(用户唯一的身份标识)、time(当前时间的时间戳)、sign(签名,由token的前几位+盐以哈希算法压缩成一定长 的 十六进制字符串,可以防止恶意第三方拼接token请求服务器)。 -
使用Token的目的
:Token的目的是为了减轻服务器的压力,减少频繁的查询数据库,使服务器更加健壮。 -
基于 Token 的身份验证
:使用基于 Token 的身份验证方法,在服务端不需要存储用户的登录记录。大概的流程是这样的:- 客户端使用用户名跟密码
请求登录
- 服务端收到请求,去验证用户名与密码
- 验证成功后,服务端会
签发一个 Token
,再把这个 Token 发送给客户端
- 客户端
收到 Token
以后可以把它存储起来
,比如放在 Cookie 里
或者 Local Storage 里 - 客户端
每次向服务端请求资源的时候
需要带着服务端签发的 Token
- 服务端收到请求,然后去
验证
客户端请求里面带着的Token
,如果验证成功
,就向客户端返回请求的数据
- 客户端使用用户名跟密码
-
token泄露问题的解决
1、在存储的时候
把token进行对称加密存储
,用时解开
。
2、将请求URL、时间戳、token三者进行合并加盐签名
,服务端校验有效性
。方法1它拿到存储的密文解不开、方法2它不知道你的签名算法和盐,两者可以结合使用。另外还可以设置token的过期时间。
在网络层面上token明文传输的话会非常的危险,所以建议一定要使用HTTPS,并且把token放在post body里。
Cookie和session的区别
存储数据类型方面
:session 能够存储任意的 java 对象
,cookie 只能存储 String 类型的对象
。cookie 在客户端,session 在服务端
。因Cookie在客户端所以可以编辑伪造,不是十分安全。- Session过多时会消耗服务器资源,大型网站会
有专门Session服务器
,Cookie存在客户端没问题。 - session保存在服务器上,当访问增多,会比较占用你服务器的性能,考虑到减轻服务器性能方面,应当使用cookie。
单个cookie保存的数据不能超过4K
,很多浏览器都限制一个站点最多保存20个cookie
。- 可以考虑将登陆信息等
重要信息存放为session
,其他信息如果需要保留,可以放在cookie中。
session与token的区别
session 和 oauth token并不矛盾,作为身份认证 token安全性比session好,因为每个请求都有签名还能防止监听以及重放攻击,而session就必须靠链路层来保障通讯安全了。如上所说,如果你需要实现有状态的会话,仍然可以增加session来在服务器端保存一些状态。
App通常用restful api跟server打交道。Rest是stateless的,也就是app不需要像browser那样用cookie来保存session,因此用session token来标示自己就够了,session/state由api server的逻辑处理。 如果你的后端不是stateless的rest api, 那么你可能需要在app里保存session。可以在app里嵌入webkit,用一个隐藏的browser来管理cookie session。
Session 是一种HTTP存储机制,目的是 为无状态的HTTP提供的持久机制
。所谓Session 认证只是简单的把User 信息存储到Session 里,因为SID 的不可预测性,暂且认为是安全的。这是一种认证手段。
而Token ,如果指的是OAuth Token 或类似的机制的话,提供的是 认证 和 授权 ,认证是针对用户,授权是针对App 。其目的是 让 某App有权利访问 某用户 的信息。这里的 Token是唯一的。不可以转移到其它 App上,也不可以转到其它 用户 上。
转过来说Session 。Session只提供一种简单的认证,即有此 SID,即认为有此 User的全部权利。是需要严格保密的,这个数据应该只保存在站方,不应该共享给其它网站或者第三方App。 所以简单来说,如果你的用户数据可能需要和第三方共享,或者允许第三方调用 API 接口,用 Token 。如果永远只是自己的网站,自己的 App,用什么就无所谓了。
token就是令牌,比如你授权(登录)一个程序时,他就是个依据,判断你是否已经授权该软件;cookie就是写在客户端的一个txt文件,里面包括你登录信息之类的,这样你下次在登录某个网站,就会自动调用cookie自动登录用户名;session和cookie差不多,只是session是写在服务器端的文件,也需要在客户端写入cookie文件,但是文件里是你的浏览器编号。Session的状态是存储在服务器端,客户端只有session id;而Token的状态是存储在客户端。
session多服务器间共享
- 可用
gemfire实现 session 复制共享
。 - 可将session
维护在 redis
中实现 session 共享。 - 同时可将 session
维护在客户端的cookie
中,但前提是数据要加密
。
这三种方式可迅速切换,而不影响应用正常执行。在实践中,首选 gemfire 或者 redis 作为 session 共享的载体,一旦 session 不稳定出现问题的时候,可以紧急切换 cookie 维护 session 作为备用,不影响应用提供服务。
单点登录中,cookie 被禁用了怎么办?
单点登录的原理是
后端生成一个 session ID,设置到 cookie,后面所有请求浏览器都会带上cookie,然后服务端从cookie获取 session ID,查询到用户信息。所以,保持登录的关键不是cookie,而是通过cookie 保存 传输的 session ID,本质是能获取用户信息的数据。
除了cookie,还常用 HTTP 请求头来传输
。但这个请求头浏览器不会像cookie一样自动携带,需手工处理。