您的位置:首页 > 编程语言 > Java开发

JavaWeb--DeepLearningCookie&Session&Token

2019-03-19 08:17 162 查看
版权声明:你天加练的全战攻城狮梦 https://blog.csdn.net/u010122604/article/details/88632688

为什么有这三个东西?
因为HTTP请求时无状态的

很久以前,web基本上就是文档的浏览而已,作为服务器,不需要记住谁再某一段时间里都浏览了什么文档,每次请求都是一个新的HTTP协议,就是请求&相应,不用关注谁刚刚发起了HTTP请求,每个请求都是全新的

随着web2.0 交互式互联网的兴起,向在线购物网站,需要登录的网站等等,需要管理会话,必须记住哪些人登录系统,哪些人往自己的购物车中放商品,就必须把每个人区分开,HTTP请求时无状态的,所以给大家发一个会话标识(session id),说白了就是一个随机的字符串,每个人收到的都不一样,每次向服务器发起HTTP请求的时候,把这个字符串一并捎过来,这样服务器就能区分开谁是谁了。

但是服务器就不开心了,需要保存所有人的session id,如果用户成千上万,将是一个巨大的开销,严重限制了服务器的扩展能力,使用两个机器组成一个集群,F通过机器A登录了系统,那Session ID 会保存在机器A上, F的下次请求被转发到机器B上,机器B没有F的Session ID。可以使用session sticky,让F的请求一直黏在机器A上,但这也不管用,要是机器A挂掉了,还得转到机器B去。如果只做session的复制,把session id在两个机器之间搬来搬去,很操蛋。

另外还有一个解决办法,把session id 集中存储到一个地方,所有的机器都来访问这个地方的数据,这样一来,就不同复制了,但是增加了单点失败的可能性,要是负责session存储的机器挂掉了,所有人都得重新登录一遍。

单点的session存储也搞出集群,增加可靠性,不管如何,session的存储对于服务器来说,可以说是一个沉重的负担。

解决问题的方式
不保存session,让每个客户端去保存,可是不保存这些session id,客户端发给服务器的session id 的确无法验证,我们无法得知是不是和发登录的用户,那些不坏好意的家伙,就可以伪造session id,为所欲为了。
使用验证:
F登录系统,发给他一个令牌(token),里面包含了F的userId,下次F再次通过http请求访问的时候,这个token通过http header带过来就可以了。在此基础上做一个数字签名,比如使用HMAC-SHA256 算法,加上一个只有服务器才知道的密钥,对数据做一个签名,把签名和数据一起作为token,由于密钥别人不知道,就无法伪造token了。

这个token在服务器端不保存,当F把这个token发过来的时候,再用同样的HMAC-SHA256 算法和同样的密钥,对数据在计算一次签名,和token中签名做个比较,如果相同,就知道F已经登陆过了,并且可以直接取到F的userId,如果不相同,数据部分肯定被篡改过,就需要告诉发送者,对不起,没有认证。

Token中的数据是明文保存的,(base64可以做编码,但不是加密),还是可以被别人看到,所以不能再其中保存像密码这样的敏感信息。
当然,如果一个人的token被别人偷走了,没有办法,我也会认为小偷就是合法用户,其实和一个人的session id 被别人偷走是一样的。

这样一来,我就不保存session id了,我只是生成了token,然后验证token,我用我的CPU计算时间获取了我的session存储空间!

解除了session id 这个负担,服务器可以轻松地做水平扩展,用户访问量增大,直接加机器就行。无状态的感觉很好。

cookie
cookie是一个非常具体的东西,指的是浏览器里面能永久存储一种数据,仅仅是浏览器实现的一种数据存储功能。 cookie由服务器生成,发送给浏览器,浏览器把cookie以K-V形式保存在某个目录下的文本文件内,下一次请求通一网站时会把该cookie发送给服务器。由于cookie是存在客户端上的,所以浏览器加入了一些限制确保cookie不会被恶意使用,同时不会占据太多磁盘空间,所以每个域的cookie数量是有限的。

session
会话,类似于你和一个人交谈,怎么知道当前和你交谈的是张三而不是李四呢?对方肯定有某种特征表名他就是张三。
session也是类似的道理,服务器要知道当前发请求给自己的是谁。为了做这种区分,服务器就要给每个客户分配不同的“身份标识”,然后 4000 客户端每次向服务器发请求的时候,都带上这个“身份标识”,服务器就知道这个请求来自与谁了。至于客户端怎么保存这个“身份标识”,可以有很多方式,对于浏览器客户端,大家都默认采用cookie的方式。

cookie和session的区别:
session是存储服务器端,cookie是存储在客户端,所以session的安全性比cookie高
获取session里的信息使用过存放在会话cookie里面的session id获取的。而session是存放在服务器的内存里,所以session里的数据不断增加会造成服务器的负担,所以会把重要的信息存储在session中,而把一些次要的东西存储在客户端的cookie里

cookie确切的说法分为两大类:会话cookie和持久化cookie。
会话cookie:是存放在客户端浏览器的内存中,他的生命周期和浏览器是一致的,当浏览器关闭会话cookie也就消失了。
持久化cookie:是存放在客户端硬盘中,持久化cookie的声明周期是我们在设置cookie时候设置的保存时间,session的信息是通过sessionid获取的,而sessionid是存放在会话cookie当中的,当浏览器关闭的时候会话cookie消失,所以sessionid也就消失了,但是session的信息还存在服务器端,只是查不到所谓的session但它并不是不存在。所以session在服务器关闭的时候,or是session过期,又或者调用了invalidate,再或者是session中某一条数据消失调用session.removeAttribute方法,session在通过调用session.getsession来创建。

Token
以下几点回让你在程序中使用基于Token的身份验证:
1 无状态,可扩展
2 支持移动设备
3 跨程序调用
4 安全

以往基于服务器的验证就是使用Session,Cookie方式进行验证
暴露出的问题:
1 Session: 每次认证用户发起请求时,服务器需要去创建一个记录来存储信息。当越来越多的用户发请求时,内存的开销也会不断增加。
2 可扩展性: 在服务端的内存中使用Session存储登录信息,伴随而来的是可扩展性问题
4 CORS(跨域资源共享):当我们需要让数据跨多台移动设备上使用时,跨域资源的共享会是一个让人头疼的问题。在使用Ajax抓取另一个宇的资源,就可以会出现禁止请求的情况。
5 CSRF(跨站请求伪造):用户在访问银行网站时,他们很容易受到跨站请求伪造的攻击,并且能够被利用其访问替他网站。

基于Token的验证原理:
1 基于Token的身份是无状态的,我们不将用户信息存在服务器or Session中。
2 这种概念解决了在服务器存储信息时的许多问题。
3 NoSession意味着你的程序可以根据需要去增减机器,而不用去担心用户是否登录。

基于Token的身份验证的过程如下:
1 用户通过用户名和密码发送请求。
2 程序验证。
3 程序返回一个签名的token 给客户端。
4 客户端储存token,并且每次用于每次发送请求。
5 服务端验证token并返回数据

每一次请求都需要token,token应该爱HTTP的头部发送从而保证了Http请求的无状态。我们同样通过设置服务器属性Access_control_Allow_Origin:* 让服务器能接受来自所有域的请求。

实现思路:
1 用户登录校验,校验成功后就返回Token给客户端
2 客户端收到数据库后保存在客户端
3 客户端每次访问API是携带Token到服务器端
4 服务器端采用filter过滤器校验。校验成功则返回请求数据,校验失败则返回错误码

我们在程序中认证了信息并取得token之后,我们便能通过这个Token做许多的事情。
我们甚至能基于创建一个基于权限的token传给第三方应用程序,这些第三方程序能够获取我们的数据

Token的优势:
无状态,可扩展
客户端存储的Tokens是无状态的,并且能够被扩展,基于这种无状态和不存储Session信息,负载均衡器可以将用户信息从一个服务器传到其他服务器上。
如果我们将已验证的信息保存在Session中,则每次请求都需要用户向已验证的服务器发送验证信息.用户量大时候,可能会造成拥堵,使用tokens之后,这些问题都影人而解,因为tokens自己hold住了用户的验证信息

安全性:
请求中发送token而不再是发送cookie能够防止CSRF(跨站请求伪造)。及时在客户端使用cookie存储token,cookie也仅仅是一个存储机制而不是用于认证。不将信息存储在Session中,服务器少了Session的操作

token是有实效性的,一段时间之后用户需要重新验证。我们也不一定要等到token自动失效,token有撤回的操作,通过token revocatation可以使一个特定的token或者一组有相同认证的token无效。

可扩展性:
tokens能够创建于其他程序共享权限的程序。例如,能将一个随便的社交账号和自己大号联系起来。当通过服务登录,我们可以将这些附属到数据流上。 使用tokens时,可以通巩固可选的全向给第三方应用程序。当用户想让另一个应用程序访问它们的数据,我们可以通过建立自己的API,得出特殊权限的tokens。

多平台跨域:
CORS(跨域资源共享),对应用程序和服务进行扩展的时候,需要接入各种各样的设备和应用程序,只要用户有一个通过了验证的token,数据和资源就能够在任何域上被请求到。

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: