• 1. HTTP连接状态保持技术组:樊 宇fanyu@cmos.chinamobile.com
  • 2. 目录1客户端与服务端交互过程2客户端解决方案3服务端解决方案4单点登录方案5常见分布式Session解决方案6在线公司分布式Session解决方案
  • 3. 1、客户端与服务端交互过程
  • 4. 什么是HTTPHTTP是hypertext transfer protocol(超文本传输协议)的简写,它是七层网络架构中的应用层协议,用于定义客户端与服务端之间交换数据的过程以及数据本身的格式。浏览器与服务器之间的一问一答的交互过程必须遵循HTTP协议。
  • 5. HTTP请求工作流程1、建立连接 2、发出请求信息 3、回送相应信息 4、关闭连接
  • 6. HTTP请求信息结构一个请求行、若干消息头、以及实体内容,其中的一些消息头和实体内容都是可选的,消息头和实体内容之间要用空行隔开。 举例: GET /books/java.html HTTP/1.1 Accept: */* Accept-Language: en-us Connection: Keep-Alive Host: localhost Referer: http://localhost/links.asp User-Agent: Mozilla/4.0 Accept-Encoding: gzip, deflate请求行一个空行多个消息头
  • 7. HTTP响应信息结构一个状态行、若干消息头、以及实体内容 ,其中的一些消息头和实体内容都是可选的,消息头和实体内容之间要用空行隔开。举例: HTTP/1.1 200 OK Server: Microsoft-IIS/5.0 Date: Thu, 13 Jul 2000 05:46:53 GMT Content-Length: 2291 Content-Type: text/html Cache-control: private ……状态行一个空行多个消息头实体内容
  • 8. HTTP状态码响应状态码用于表示服务器对请求的各种不同处理结果和状态,它是一个三位的十进制数。响应状态码可归为5种类别,使用最高位为1到5来进行分类,如下所示: 1、100~199:表示成功接收请求,要求客户端继续提交下一次请求才能完成整个处理过程 。 2、200~299:表示成功接收请求并已完成整个处理过程 。 3、300~399:为完成请求,客户需进一步细化请求。 4、400~499:客户端的请求有错误。 5、500~599:服务器端出现错误。状态码大全:http://tool.oschina.net/commons?type=5
  • 9. ????问题HTTP协议是一种无状态的协议,WEB服务器本身不能识别出哪些请求是同一个浏览器发出的 ,浏览器的每一次请求都是完全独立的。作为 web 服务器,必须能够采用一种机制来唯一地标识一个用户,同时记录该用户的状态。
  • 10. 会话和会话状态WEB应用中的会话是指一个客户端浏览器与WEB服务器之间连续发生的一系列请求和响应过程。 WEB应用的会话状态是指WEB服务器与浏览器在会话过程中产生的状态信息,借助会话状态,WEB服务器能够把属于同一会话中的一系列的请求和响应过程关联起来。
  • 11. 如何实现有状态的会话服务器端程序要能从大量的请求消息中区分出哪些请求消息属于同一个会话,即来自同一个浏览器的访问请求,这需要浏览器对其发出的每个请求消息都进行标识:属于同一个会话中的请求消息都附带同样的标识号,不同会话的请求消息附带不同的标识号,这个标识号就称之为会话ID(SessionID)。 目前常用以下两种技术机制实现会话保持: Cookie Session
  • 12. 会话保持流程首次交互: 1、客户端向服务端发送第一次请求 2、服务端的容器产生该用户唯一sessionID的session对象,并设置值 3、容器响应 Set-Cookie:JSESSIONID= … 4、浏览器解析Cookie,保存至浏览器文件
  • 13. 会话保持流程再次交互: 1、再次请求 2、容器获取sessionID,关联HttpSession 3、响应无SetCookie
  • 14. 2、客户端解决方案
  • 15. 什么是cookie cookie是在浏览器访问WEB服务器的某个资源时,由WEB服务器在HTTP响应消息头中附带传送给浏览器的一个小文本文件。 一旦WEB浏览器保存了某个Cookie,在以后每次访问该WEB服务器时,都会在HTTP请求头中将这个Cookie回传给WEB服务器。 cookie机制采用的是在客户端保持 HTTP 状态信息的方案。 实现原理: WEB服务器通过在HTTP响应消息中增加Set-Cookie响应头字段将Cookie信息发送给浏览器;浏览器则通过在HTTP请求消息中增加Cookie请求头字段将Cookie回传给WEB服务器。 特征: 1、一个Cookie只能标识一种信息,它至少含有一个标识该信息的名称(KEY)和设置值(VALUE)。 2、一个WEB站点可以给一个浏览器发送多个Cookie,一个浏览器也可以存储多个WEB站点提供的Cookie。 3、Cookie的大小限制为4KB。
  • 16. cookie机制图解 ①第一次访问不存在 Server1的Cookie ④写入Server1 的Cookie③第一次响应 Set-Cookie2: key=value ②第一次访问请求 WEB Server1 WEB Server2 浏览器 Server1 的Cookie Server2 的CookieCookie存储区 ⑤后续访问存在 Server1的Cookie ⑥后续访问请求 Cookie: key=value
  • 17. Java Cookie工具类 Servlet API中提供了一个javax.servlet.http.Cookie类来封装Cookie信息,它包含有生成Cookie信息和提取Cookie信息的各个属性的方法。 方法名setValue/getValue设置和获取cookie的值setMaxAge/getMaxAge设置 和获取cookie 的最大生存时间,以秒为单位setPath/getPath设置和获取浏览器将此 cookie 返回到的服务器上的路径addCookieHttpServletResponse接口中,在发送给浏览器的HTTP响应消息中增加一个Set-Cookie响应头字段getCookiesHttpServletRequest接口中,从HTTP请求消息的Cookie请求头字段中读取所有的Cookie项
  • 18. JS Cookie工具类
  • 19. Cookie的发送1.创建Cookie对象 2.设置最大时效 3.将Cookie放入到HTTP响应报头 发送cookie需要使用addCookie()方法,将cookie插入到一个 Set-Cookie HTTP响应报头中。由于这个方法并不修改任何之前指定的Set-Cookie报头,而是创建新的报头,因此将这个方法称为是addCookie,而非setCookie。
  • 20. 会话cookie和持久cookie的区别 如果不设置过期时间,则表示这个cookie生命周期为浏览器会话期间,只要关闭浏览器窗口,cookie就消失了。这种生命期为浏览器会话期的cookie被称为会话cookie。会话cookie不保存在硬盘上,而是保存在内存里。 如果设置了过期时间,浏览器就会把cookie保存到硬盘上,关闭后再次打开浏览器,这些cookie依然有效直到超过设定的过期时间。 存储在硬盘上的cookie可以在不同的浏览器进程间共享,比如两个IE窗口。而对于保存在内存的cookie,不同的浏览器有不同的处理方式。
  • 21. cookie的读取 1.调用request.getCookies 要获取浏览器发送来的cookie,需要调用HttpServletRequest的getCookies方法,这个调用返回Cookie对象的数组,对应由HTTP请求中Cookie报头输入的值。 2.对数组进行循环,调用每个cookie的getName()方法,直到找到感兴趣的cookie为止。
  • 22. 3、服务端解决方案
  • 23. Session机制session机制采用的是在服务器端保持 HTTP 状态信息的方案 。 服务器使用一种类似于散列表的结构来保存信息。 当程序需要为某个客户端的请求创建一个session时,服务器首先检查这个客户端的请求里是否包含了一个sessionID标识,如果已经包含一个sessionID则说明以前已经为此客户创建过session,服务器就按照sessionID把这个session检索出来使用。如果客户请求不包含sessionID,则为此客户创建一个session并且生成一个与此session相关联的sessionID,这个sessionID将在本次响应中返回给客户端保存。
  • 24. 保存sessionID的方式 保存sessionID的方式可以采用cookie,这样在交互过程中浏览器可以自动的按照规则把这个标识发送给服务器。 由于cookie可以被人为的禁用,必须有其它的机制以便在cookie被禁用时仍然能够把sessionID传递回服务器,经常采用的一种技术叫做URL重写,就是把sessionID附加在URL路径的后面。网络在整个交互过程中始终保持状态,就必须在每个客户端可能请求的路径后面都包含这个sessionID。
  • 25. Session cookiesession通过SessionID来区分不同的用户, session是以cookie或URL重写为基础的,默认使用cookie来实现,系统会创造一个名为JSESSIONID的输出cookie,这称之为session cookie,以区别persistent cookies(也就是我们通常所说的cookie),session cookie是存储于浏览器内存中的,并不是写到硬盘上的,通常看不到JSESSIONID,但是当把浏览器的cookie禁止后,web服务器会采用URL重写的方式传递sessionID,这时地址栏可以看到。 session cookie针对某一次会话而言,会话结束session cookie也就随着消失了,而persistent cookie只是存在于客户端硬盘上的一段文本。 关闭浏览器,只会是浏览器端内存里的session cookie消失,但不会使保存在服务器端的session对象消失,同样也不会使已经保存到硬盘上的持久化cookie消失。
  • 26. Session的创建与删除 Session创建: 一个常见的错误是以为session在有客户端访问时就被创建,然而事实是直到某server端程序调用HttpServletRequest.getSession(true) 或者 HttpServletRequest.getSession()这样的语句时才会被创建。 session删除: A.程序调用HttpSession.invalidate() B.距离上一次收到客户端发送的sessionID时间间隔超过了session的最大有效时间 C.服务器进程被停止
  • 27. Session的超时管理 WEB服务器无法判断当前的客户端浏览器是否还会继续访问,也无法检测客户端浏览器是否关闭,即使客户已经离开或关闭了浏览器,WEB服务器还要保留与之对应的HttpSession对象。 随着时间的推移而不断增加新的访问客户端,WEB服务器内存中将会因此积累起大量的不再被使用的HttpSession对象,并将最终导致服务器内存耗尽。 WEB服务器采用“超时限制”的办法来判断客户端是否还在继续访问,如果某个客户端在一定的时间之内没有发出后续请求,WEB服务器则认为客户端已经停止了活动,结束与该客户端的会话并将与之对应的HttpSession对象清理。 如果客户端浏览器超时后再次发出访问请求,WEB服务器则认为这是一个新的会话的开始,将重新创建HttpSession对象和分配新的会话标识号。
  • 28. HttpSession接口中的方法 方法名方法描述getId返回会话IDgetCreationTime/getLastAccessedTime返回表示会话创建和最后访问日期和时间的一个长整型setMaxInactiveInterval/getMaxInactiveInterval如果没有与客户端发生交互,设置和返回会话存活的最大秒数isNew如果客户端仍未加入到会话,返回true。当会话首次被创建,会话ID被传入客户端,但客户端仍未进行包含此会话ID的第二次请示时,返回trueinvalidate使得会话被终止,释放其中任意对象setAttribute/getAttribute从会话中存储和获取属性removeAttribute从会话中删除对象getAttributeNames返回当前会话所有属性名的枚举值
  • 29. HttpServletRequest接口中的Session方法 方法名方法描述getSession(boolean create)返回当前HTTP会话,如果不存在,则创建一个新的会话,create参数为trueisRequestedSessionIdValid如果客户端返回的会话ID仍然有效,则返回trueisRequestedSessionIdFromCookie如果请求的会话ID由一个Cookie对象提供,则返回true,否则为falseisRequestedSessionIdFromURL 如果请求的会话ID在请求URL中解码,返回true,否则为false
  • 30. Session域范围的属性
  • 31. 4、单点登录方案
  • 32. 什么是单点登录单点登录(Single Sign On),简称为 SSO,是在多个应用系统中,用户只需要登录一次就可以访问所有相互信任的应用系统。 实现单点登录说到底要解决如何产生和存储信任,再就是其他系统如何验证这个信任的有效性,因此要点也就以下两个: 存储信任 验证信任
  • 33. 方案一:Cookie作为凭证最简单的单点登录实现方式,是使用cookie作为媒介,存放用户凭证。用户登录父应用之后,应用返回一个加密的cookie,当用户访问子应用的时候,携带上这个cookie,授权应用解密cookie并进行校验,校验通过则登录当前用户。 缺点: Cookie不安全 不能跨域实现免登
  • 34. 方案二:JSONP实现通过使用JSONP技术,解决跨域问题。用户在父应用中登录后,跟Session匹配的Cookie会存到客户端中,当用户需要登录子应用的时候,授权应用访问父应用提供的JSONP接口,并在请求中带上父应用域名下的Cookie,父应用接收到请求,验证用户的登录状态,返回加密的信息,子应用通过解析返回来的加密信息来验证用户,如果通过验证则登录用户。
  • 35. 方案三:页面重定向父应用提供一个GET方式的登录接口,用户通过子应用重定向连接的方式访问这个接口,如果用户还没有登录,则返回一个的登录页面,用户输入账号密码进行登录。如果用户已经登录了,则生成加密的Token,并且重定向到子应用提供的验证Token的接口,通过解密和校验之后,子应用登录当前用户。
  • 36. 方案四:独立认证系统 大型企业级应用会把授权的逻辑与用户信息的相关逻辑独立成一个系统,称为用户中心。 用户中心不处理业任何务逻辑,只是处理用户信息的管理以及认证授权给第三方应用。第三方应用需要登录的时候,则把用户的登录请求转发给用户中心进行处理,用户处理完毕返回凭证,第三方应用验证凭证,通过后就登录用户。
  • 37. OAuth2.0授权协议OAuth(开放授权)是一个开放标准,允许第三方系统在用户授权的前提下访问在用户在服务商存储的数据。而这种授权无需将用户名和密码提供给该第三方系统。 OAuth允许用户提供一个令牌给第三方系统,一个令牌对应一个特定的第三方系统,同时该令牌只能在特定的时间内访问特定的资源。
  • 38. OAuth2.0客户端的授权模式1、授权码模式(authorization code)。是功能最完整、流程最严密的授权模式。它的特点就是通过客户端的后台服务器,与“服务提供商”的认证服务器进行交互。 2、简化模式(implicit)。不通过第三方应用程序的服务器,直接在浏览器中向认证服务器申请令牌,跳过了"授权码"这个步骤。所有步骤在浏览器中完成,令牌对访问者是可见的,且客户端不需要认证。 3、密码模式(resource owner password credentials)。用户向客户端提供自己的用户名和密码。客户端使用这些信息,向"服务商提供商"索要授权。 4、客户端模式(client credentials)。客户端以自己的名义,而不是以用户的名义,向"服务提供商"进行认证。在这种模式中,用户直接向客户端注册,客户端以自己的名义要求"服务提供商"提供服务,其实不存在授权问题。
  • 39. 授权码模式(A)用户访问客户端,后者将前者导向认证服务器。 (B)用户选择是否给予客户端授权。 (C)假设用户给予授权,认证服务器将用户导向客户端事先指定的"重定向URI"(redirection URI),同时附上一个授权码。 (D)客户端收到授权码,附上早先的“重定向URI”,向认证服务器申请令牌。这一步是通过客户端的后台服务完成的,对用户不可见。 (E)认证服务器核对了授权码和重定向URI,确认无误后,向客户端发送访问令牌(access token)和更新令牌(refresh token)。
  • 40. 5、分布式session解决方案
  • 41. 应用的集群部署需考虑分布式session会话的管理问题。 如应用集群中存在A、B两台服务器,用户在第一次访问应用时,Nginx通过负载均衡机制将用户请求转发到A服务器,A服务器给用户创建一个会话Session。当用户再次发起请求时,Nginx将其负载均衡至B服务器,B服务器并不存在当前用户会话Session,因此用户需要重新完成登录操作。 如果不做任何处理,用户将出现频繁登录现象,很大程度上降低用户体验,导致用户的流失。分布式session问题
  • 42. Session Sticky让负载均衡器根据每次请求的会话标识进行请求转发,通过该机制保证同一会话的请求每次都能落到同一台服务器上面,这种方式称为Session Sticky方式。存在问题        1. 如果一台Web服务器宕机或者重启了,服务器上的会话数据会丢失,用户需要重新登录。         2. 会话标识是应用层信息,如果负载均衡器要将同一个会话的请求保存到同一Web服务器上,就需要对应用层进行解析,这给负载均衡器带来额外的开销。         3. 负载均衡器变为一个有状态的节点,要保存会话与Web应用服务器间映射关系。和无状态的节点相比,增大内存消耗和容灾难度。
  • 43. Session Replication该方案不要求负载均衡器保存会话与Web应用服务器间映射关系。只需在Web服务器之间增加会话数据同步,通过同步机制保证不同Web服务器之间Session数据的一致性。一般应用容器都支持Session Replication方式,与Session Sticky方案相比,Session Replication方式对负载均衡器没有过多要求。存在问题  1. 同步Session数据造成额外的网络开销。只要Session数据发生变化,就要将数据同步到所有应用服务器,服务器越多,同步带来的网络开销越大。    2. 每台Web服务器都要保存所有Session数据,如果整个集群的Session数据量很大,每台服务器保存Session数据量将消耗大量的内存。 
  • 44. Session 集中管理该方案将Session数据集中存储,不同Web服务器从同一容器获取Session数据,如数据库,分布式缓存,分布式文件系统等。该方案很好解决了Session Replication方案中内存消耗和会话数据同步带来的网络带宽负载严重的问题。实现方案1. 基于容器插件的实现 ,比如基于Tomcat的tomcat-redis-session-manager。 优点:对项目透明,无需修改代码。 缺点:过于依赖容器,开发者难以维护 2.使用框架的会话管理工具,spring-session,shrio分布式会话管理。 优点:既不依赖容器,无需改动代码。
  • 45. 6、在线公司分布式session解决方案
  • 46. 结合负载均衡服务器与Redis集群的分布式Session缓存方案用户通过浏览器或移动应用请求Session的读写操作,负载均衡服务器将请求分发至应用服务器,应用服务器从Redis集群中进行Session的存取操作。 负载均衡服务器能够将处理压力分摊至各应用服务器,提高了服务的健壮性和效率。 配置Redis主从集群,主Redis会话数据热备份至从Redis ,当主Redis宕机了,系统自动切换至从Redis ,从而保证系统缓存方面高可用。 使用Redis无需专门添加会话过期调度器,可以借助Redis自身的过期策略来完成。
  • 47. Thank you!