介绍由于HTTP协议是无状态的,在操作完成关闭浏览器后,客户端和服务器端的连接就会断开,所以我们必须有一个机制来保证客户端和服务器之间会话的连续性,也称为认证,最常见的应用场景是维护用户的登录状态。最基本的认证方式是使用Sesson-Cookie。30sGraphicalSesson-CookieAuthentication以保持用户登录为例,Sesson-Cookie认证的具体步骤如下:1)客户端(浏览器):向服务器发送登录信息(用户名和密码),请求登录验证;2)服务器:验证登录信息。验证通过后,服务器(如Tomcat)会自动为本次请求开辟一块内存空间(一个Session对象),用户信息(如登录保留时间是否过期)可以手动保存在Session中目的。然后,服务器会自动为这个Session对象生成一个唯一标识sessionID,并在HTTP响应头(Header)的Set-Cookie:JSESSIONID=XXXXXXX中设置这个sessionID。所以Session的实现依赖于Cookie3)Client:收到服务端的响应后,会解析响应头,根据set-Cookie将sessionId保存在本地Cookie中,从而使client(browser)会在第一次HTTP请求的请求头中自动附加域名下的cookie信息;4)Server:当收到客户端请求时,会解析请求头Cookie中的sessonId,然后根据sessonId找到Sesson对象,从而获取User信息;拦截器可以用来在每次请求前尝试获取Session对象:在session存活期间,我们认为client一直处于活动状态(用户登录),一旦session过期,可以认为client已停止并且服务器交互(用户注销)。如果遇到cookie被禁用的情况,一般的做法是将这个sessionID放在URL参数中。这也是面试中经常被问到的问题。可能有同学会问,为什么不直接把所有的数据都存到cookie里,返回整个session,把sessionID存到cookie里呢?Cookie长度限制:首先,最基本的,Cookie是有长度限制的,也就是限制了它可以存储的数据的长度。每次客户端访问时都必须返回这些cookie。如果cookie中存储的数据很多,这无疑会增加客户端与服务器之间的数据传输量,增加服务器的压力。安全性:Session数据其实是属于服务端的,cookies是属于客户端的。将本应保存在session中的数据放入客户端cookie中,使得服务端数据延伸到外网和客户端,显然在安全问题上存在问题。当然,我们可以对这些数据进行加密,但从技术上讲,物理接触是最安全的。补充阅读Sesson-Cookie认证伪代码登录:拦截器:在每次请求前查找Sesson对象,从而获取用户信息。可以看出,在一个session中,两次请求得到的Session对象其实是同一个对象。上面说到服务端根据cookie中的sessionID找到Session对象,但是在上面的代码中,我们只是手动将用户数据设置到Session中,并没有关于Cookie的代码(将SessionId设置到Cookie中)显然,这些必须由服务器(如Tomcat)自动完成。第一次获取Session时,即调用request.getSession(),服务端会自动创建一个Session对象(Session是一个集合,又是一个Map集合),并保存在服务端的Session集合中SessionId作为标识键。也就是说根据SessionId可以得到对应Session的引用。同时会创建一个key名为JSESSIONID的cookie返回给浏览器,cookie的值为SessionId。存储SessionId的cookie会随着请求上传到服务器,所以在同一个会话中,无论哪个请求得到的都是同一个Session对象。Sesson-Cookie认证的缺点及解决方法。这种机制在单体应用时代被广泛使用。但是,随着分布式时代的到来,Session的缺点逐渐暴露出来。比如我们有多个服务器,客户端1向服务器发送请求。由于负载均衡的存在,请求被转发到服务器A,所以服务器A创建并存储了Session。然后,客户端1又向服务器发送了一个请求,但是这次请求是负载均衡到服务器B的,此时服务器B没有保存服务器A的session,导致session失效。用户在上一个界面登录,跳到下一个界面后又退出,这显然是不合理的。当然,这个其实有很多解决办法。其实就是如何解决多台服务器之间session共享的问题:SessionReplication是最容易想到的,由于服务器B没有服务器A存储Session,那么服务器之间同步session数据就结束了.这种方案的问题也很明显:同步Session数据会带来额外的网络带宽开销。只要会话数据发生变化,就需要将数据同步到所有其他机器上。机器越多,同步带来的网络带宽开销就越大。每个Web服务器都必须保存所有会话数据。如果整个集群的session数据非常多(比如很多人同时访问网站),每个服务器保存session数据的内存占用会很严重。SessionSticky从名字也能看出来。Sticky允许负载均衡器根据每个请求的会话ID转发请求,确保一个会话中的每个请求都可以落在同一台服务器上。有一个问题:如果一台服务器宕机或者重启,存储在上面的Session数据就会丢失,用户需要重新登录。负载均衡器成为有状态节点,因为它需要保存从Session到特定服务器的映射。与之前的无状态节点相比,内存消耗会更大,容灾也更麻烦。会话数据的集中存储。每个服务器的session数据都存储在一个外部介质中,比如Redis或者MySQL,然后所有的服务器都可以从这个外部介质中获取session。存在的问题也很明显:过度依赖外存,如果集中存储Session的外存机器出现问题,会直接影响到我们的应用
