会话
会话是指一个终端用户与交互系统进行通讯的过程,比如从输入账户密码进入操作系统到退出操作系统就是一个会话过程。会话较多用于网络上,TCP的三次握手就创建了一个会话,TCP关闭连接就是关闭会话。
Session代表服务器与浏览器的一次会话过程,这个过程是连续的,也可以时断时续的。
在javaEE中一次会话指的是:打开浏览器,访问服务器,直到关闭浏览器,称为一次会话。
在多次HTTP连接间维护用户与同一用户发出的不同请求之间关联的情况
会话能够把用户与同一用户发出的不同请求之间关联起来。不同用户的会话应当是相互独立的。
会话一旦建立就应当一直存在,直到用户空闲时间超过了某一个时间界限,容器才应当释放该会话资源。
在会话的存活期间,用户可能给服务器发送了很多请求,该用户的这些请求信息都可以存储在会话中。
1 ,建立tcp连接
2 ,发出请求文档
3 ,发出响应文档
4 ,释放tcp连接
一次会话就是建立了一次tcp的连接,但是可以发送很多次HTTP请求,session记录了用户信息,于是就可以判断这些请求都来自同一个用户
cookie
- 存在于浏览器的进程中;称为会话Cookie
浏览器关闭,会话cookie结束,浏览器打开,它会从硬盘中将cookie加载到内存中来 - 存在于硬盘上。(我把它叫永久cookie)
要点
浏览器对每个域(即每个网站)所能存储的cookie数量是有限制的。
cookie由服务器生成,发送给浏览器,浏览器把cookie以kv(键值对)形式保存到某个目录下的文本文件内,下一次请求同一网站时会把该cookie发送给服务器由于cookie是存在客户端上的,所以浏览器加入了一些限制确保cookie不会被恶意使用,同时不会占据太多磁盘空间,所以每个域的cookie数量是有限的。服务器生成cookie,浏览器保存cookie,只要用户不清除cookie,它就是永久保存到用户本地的
session对象
生命周期
用户打开一个浏览器,访问一个网站的网页,用户和该网站就建立了一次会话。【不同浏览器访问同一网站属于不同会话。因为不同浏览器访问同一网站时它们携带的cookie里的sessionId是不同的。------网站的“记住我”----(相对而言)实际记住的是你访问网站时携带的cookie里的sessionId】,如果是首次会话,Servlet容器会创建一个新的HttpSession对象(即session对象),并为它分配一个唯一标识符即sessionId,当首次请求结束后,服务器通过response对象,将这个sessionId保存到浏览器的cookie里,存入本地。
下一次请求时,服务器将从cookie里取出sessionId,然后根据这个Sessionid在内存中找到之前创建的session对象,提供给请求使用。如果没有匹配的,servlet容器就会新建一个session对象。
sessionId失效了,session对象也就被销毁了
注意:session对象被销毁了,sessionId失效了,并不代表着浏览器和服务器的一次会话结束了。会话的开始和结束只与tcp的连接和关闭有关。session对象不过是一次tcp中多次http请求的’’中间产物’‘而已
结束方法有两种:
一个是调Session.invalidate()方法,使session对象强制失效,不过这个方法在实际的开发中,并不推荐,可能在强制注销用户的时候会使用;----使sessionId失效
一个是当前用户和服务器的交互时间超过默认时间后,Session会失效
可以调用Session.setMaxInactiveInterval(10)方法来设置Session的空闲时间
空闲时间也就是说在规定时间内如果有重新访问则时间重置,如果没有访问那么SessionID就会失效
注意:浏览器关闭时,它和服务器的一次会话结束,但服务器的session对象并不会被销毁。因为sessionId还处于有效期,服务器还处于运行状态。而且浏览器关闭时,浏览器并没有向服务器发送任何请求来关闭Session。如果想在浏览器关闭时,通过客户端销毁session。我们可以在所有的客户端页面里使用js的window.onclose来监视浏览器的关闭动作,然后向服务器发送一个请求来关闭Session(只是请求,至于销不销毁session的决定权还是在服务器手里),但是这种做法在实际的开发中也是不推荐使用的,最正常的办法就是不去管它,让它等到默认的时间后,自动销毁。
Session 对象最常见的一个用法就是存储用户的首选项(用户对于该网站的偏好设置,用户名,用户头像…)。例如,如果用户指明不喜欢查看图形,就可以将该信息存储在 Session 对象中
在一次会话中,session对象中的变量可以在同一网站的多个网页间共享。
如果web服务器做了负载均衡,那么下一个操作请求到了另一台服务器的时候session会丢失。
1.Seesion:每次认证用户发起请求时,服务器需要去创建一个记录来存储信息。当越来越多的用户发请求时,内存的开销也会不断增加。
2.可扩展性:在服务端的内存中使用Seesion存储登录信息,伴随而来的是可扩展性问题。
3.CORS(跨域资源共享):当我们需要让数据跨多台移动设备上使用时,跨域资源的共享会是一个让人头疼的问题。在使用Ajax抓取另一个域的资源,就可以会出现禁止请求的情况。
4.CSRF(跨站请求伪造):用户在访问银行网站时,他们很容易受到跨站请求伪造的攻击,并且能够被利用其访问其他的网站。
在这些问题中,可扩展行是最突出的。因此我们有必要去寻求一种更有行之有效的方法
request
request对象中的变量在一次请求中有效,在同一网站的多个网页间共享。而session是在用户的多次请求中都有效
token
tokens 是多用户下处理认证的最佳方式。它解决了session暴露的一系列问题。不保存session id 了, 我只是生成token , 然后验证token , 我用我的CPU计算时间获取了我的session 存储空间 !…“我们不做存储,只做演算和验证”。----基于hash算法(区块链,git也是基于hash算法。----hash真的太神奇了,即节约了时间和空间,还保证了安全性)
1.无状态、可扩展
在客户端存储的Tokens是无状态的,并且能够被扩展。基于这种无状态和不存储Session信息,负载负载均衡器能够将用户信息从一个服务传到其他服务器上。
如果我们将已验证的用户的信息保存在Session中,则每次请求都需要用户向已验证的服务器发送验证信息(称为Session亲和性)。用户量大时,可能会造成一些拥堵。
但是不要着急。使用tokens之后这些问题都迎刃而解,因为tokens自己hold住了用户的验证信息。
2.安全
请求中发送token而不再是发送cookie能够防止CSRF(跨站请求伪造)。即使在客户端使用cookie存储token,cookie也仅仅是一个存储机制而不是用于认证。不将信息存储在Session中,让我们少了对session操作。
token是有时效的,一段时间之后用户需要重新验证。我们也不一定需要等到token自动失效,token有撤回的操作,通过token revocataion可以使一个特定的token或是一组有相同认证的token无效。
3.可扩展性
Tokens能够创建与其它程序共享权限的程序。例如,能将一个随便的社交帐号和自己的大号(Fackbook或是Twitter)联系起来。当通过服务登录Twitter(我们将这个过程Buffer)时,我们可以将这些Buffer附到Twitter的数据流上(we are allowing Buffer to post to our Twitter stream)。
使用tokens时,可以提供可选的权限给第三方应用程序。当用户想让另一个应用程序访问它们的数据,我们可以通过建立自己的API,得出特殊权限的tokens。
4.多平台跨域(支持移动设备,跨程序调用)
我们提前先来谈论一下CORS(跨域资源共享),对应用程序和服务进行扩展的时候,需要介入各种各种的设备和应用程序。
只要用户有一个通过了验证的token,数据和资源就能够在任何域上被请求到。
Access-Control-Allow-Origin: *
1.用户通过用户名和密码发送请求。
2.程序验证。
3.程序返回一个签名的token 给客户端。
4.客户端储存token,并且每次用于每次发送请求。
5.服务端验证token并返回数据。