Tomcat 服务器 Session的实现
来源:互联网 发布:现在还有网络聊天室吗 编辑:程序博客网 时间:2024/05/22 12:41
结合《HTTP权威指南》和《How Tomcat Works》话一话我所理解的Session以及Tomcat下的实现方式!
Session是什么?
在开始正式讨论之前,我们首先探讨一些原理性的问题,什么是session,它可以用来做什么!
我们每天都会浏览各种网站,不同的用户浏览网站的目的不同,在该网站上留下的历史也不同,为了提供个性化的服务,服务器就需要记录和识别用户!一个用户可以在不同地方,利用不同设备访问网站,服务器如何知道“我是谁”呢?很多人一下子就想到用户名和密码,对没错,这的确是一种方式。但是网站访问是一个连续的过程,每次访问都携带用户名和密码的做法提高了用户风险,更重要的是,如何解决非注册用户的问题呢,一些用户习惯每天打开新闻站点,但是他只是浏览信息,不想输入任何个人信息去注册网站,这样的用户如何提供个性化服务呢!
看看现实生活中政府是如何识别“我是谁”,并且提供差异服务的。我们每个人都有一张身份证,是政府机关发给我们的。身份证只是一个人的基本信息,例如姓名,身份证号,住址。上面并不会纪录你的学历,你的婚姻状况。当我需要这些信息的时候,我们提供身份证,相关的单位就会提供相关证明,例如在很多省份在购买房产的时候,需要未婚人士提供一个单身证明,我们只要向相应的政府机构提供身份证,就可以获取到这些“被认可的”信息。
可以抽象的理解为,政府颁发了一个身份证给个人,当你需要政府服务的时候,只需要提供你的身份证,这样政府就会从它自己维护的数据中,获取你的更多个人信息,提供差异化服务。
身份证会具有有效期,当身份证过期的时候,需要从新申请,否则持有的身份证就会无效。
哪么,可否效仿这个过程,网站服务器“颁发”一个身份证给用户,用户每次访问都带着这个身份证,网站服务器根据这个身份证获取用户更多信息,这样不就可以获取个性化服务了么!当身份证过期的时候,需要用户从新申请。
现在我们要讨论的问题渐渐浮出水面了。我们和服务器之间的交互过程,可以理解为一个Session,直白的翻译就是一次会话,而每次我们携带的身份信息,是通过Cookie的方式实现的。
在《HTTP权威指南中》这样描述了用Cookie实现的身份认证过程。
Cookie的作用就好像服务器,给用户发的一个身份证,上面写着,“我叫XX,地址”,用户访问服务器的时候,携带着这些信息,服务器会读取所有的这些信息。
用户首次访问Web 站点时,服务器对用户一无所知。为了能够在用户下次访问的时候,识别出这个用户,站点给用户“拍上”一个独有的cookie,这样以后服务器就可以识别出这个用户了。Cookie包含了一个由名字=值这样的信息构成的列表,并通过Set-Cookie或者Set-Cookie2 HTTP响应首部返回给用户。浏览器再下次访问站点的时候,会在Cookie请求首部中,原封不动地携带服务器发送过来的Cookie数据。
其实Cookie的可以携带任意信息,它也是服务器维护用户Session的最常用的手段的一种。服务器真对用户的访问,创建一个拥有唯一ID的Session,然后通过Set-Cookie把这个SessionId贴到用户身上。用户每次访问服务器都带着这个SessionId,服务器就可以通过SessionId找出对应的Session对象,识别出用户了。
当然这仍然是很抽象的描述,不同的Web服务器实现这个机制也有很大差异。下面通过Tomcat的源代码来看一下Tomcat作为Web服务器,如何维护Session,如何根据Cookie来获取用户Session的。
Tomcat Session的实现
大概的流程可以分为如下几个步骤。
1. 从Cookie中获取SessionID
针对每一次用户的请求,HTTPProcessor负责解析用户请求,会对HTTP请求头部分析,如果发现存在jsessionid这样的cookie,就把cookie值set到HttpSevletRequest对象中
if (name.equals("cookie")) { Cookie cookies[] = RequestUtil.parseCookieHeader(value); for (int i = 0; i < cookies.length; i++) { if (cookies[i].getName().equals("jsessionid")) { // Override anything requested in the URL if (!request.isRequestedSessionIdFromCookie()) { // Accept only the first session id cookie request.setRequestedSessionId(cookies[i].getValue()); request.setRequestedSessionCookie(true); request.setRequestedSessionURL(false); } } request.addCookie(cookies[i]); }}
2. 获取Session,如果不存在创建新Session
当需要使用Session访问其中内容的时候,会调用Request的getSession方法
private HttpSession doGetSession(boolean create) { // There cannot be a session if no context has been assigned yet if (context == null) return (null); // Return the current session if it exists and is valid if ((session != null) && !session.isValid()) session = null; if (session != null) return (session.getSession()); // Return the requested session if it exists and is valid Manager manager = null; if (context != null) manager = context.getManager(); if (manager == null) return (null); // Sessions are not supported if (requestedSessionId != null) { try { session = manager.findSession(requestedSessionId); } catch (IOException e) { session = null; } if ((session != null) && !session.isValid()) session = null; if (session != null) { return (session.getSession()); } } // Create a new session if requested and the response is not committed if (!create) return (null); if ((context != null) && (response != null) && context.getCookies() && response.getResponse().isCommitted()) { throw new IllegalStateException (sm.getString("httpRequestBase.createCommitted")); } session = manager.createSession(); if (session != null) return (session.getSession()); else return (null);}
简而言之如果之前设置过SessionId,那么request会在Manager中寻找Session,如果有则直接使用,如果不存在,那么就让Manager创建一个Session。
需要补充一点,Tomcat的Session的创建和维护是通过实现Manager接口实现的,其中StandardManager是标准实现,当然真对不同应用场景,例如集群Tomcat,Session需要各个服务器共享,则需要使用不同的Manager来实现Session的维护。
3. 如果Session存在,在Response中,设置SetCookie
在HTTPResponseBase中的SetHeader方法中,检查Request中Session对象是否存在,如果存在,则把SessionId写在Set-Cookie首部
if ((session != null) && session.isNew() && (getContext() != null) && getContext().getCookies()) {Cookie cookie = new Cookie(Globals.SESSION_COOKIE_NAME, session.getId());cookie.setMaxAge(-1);String contextPath = null;if (context != null) contextPath = context.getPath();if ((contextPath != null) && (contextPath.length() > 0)) cookie.setPath(contextPath);else cookie.setPath("/");if (hreq.isSecure())cookie.setSecure(true);addCookie(cookie);}// Send all specified cookies (if any)synchronized (cookies) {Iterator items = cookies.iterator();while (items.hasNext()) {Cookie cookie = (Cookie) items.next();outputWriter.print(CookieTools.getCookieHeaderName(cookie));outputWriter.print(": ");outputWriter.print(CookieTools.getCookieHeaderValue(cookie));outputWriter.print("\r\n");}}
其实
SESSION_COOKIE_NAME
就是JSESSIONID,至于tomcat为什么使用这个字符串,可能就要和开发tomcat的程序员探讨一下了,其实她可以叫任何名字。
我们注意到在设置Cookie的时候,有一个CookieTools.getCookieHeaderName的方法,该方法根据HTTP版本号,决定使用Set-Cookie还是Set-Cookie2
public static String getCookieHeaderName(Cookie cookie) { int version = cookie.getVersion(); if (version == 1) { return "Set-Cookie2"; } else { return "Set-Cookie"; }}
4. 浏览器验证
首先我初次请求服务器,浏览器发送的数据如下:
可以看出来,浏览器发送的Cookie中,不存在JSESSIONID,因此此刻Session还并没有创建和维护起来。
不过在服务器的Response中可以看到Set-Cookie 首部
此时,服务器已经把会话建立起来,并且分配了唯一的标示,并且告诉浏览器:“下次来要告诉我你是谁哦”
然后我们刷一下浏览器,再次请求服务器,可以看到Request如下:
可以看到,这次访问Cookie中已经加上了JSESSIONID,服务器可以利用这个SessionID,从本地找到Session对象,拿到记录下来的用户行为或者用户信息了。
- Tomcat 服务器 Session的实现
- Tomcat 服务器 Session的实现
- 负载均衡下的多台tomcat服务器,通过memcache实现session共享
- tomcat原理及安装及反向代理、会话保持、session集群和session共享服务器的实现(一)
- 负载均衡时使用Spring Session和SpringData来实现多台tomcat服务器的session同步
- memcached实现集群tomcat的session共享
- memcached实现tomcat集群的session共享
- nginx+memcahed+tomcat实现session的资源共享
- tomcat session server基于memcached的实现
- 用Redis存储Tomcat集群的Session实现session共享
- Tomcat服务器session持久化
- Tomcat服务器session持久化
- Tomcat服务器session持久化
- safari浏览器 session tomcat服务器
- tomcat服务器redis管理session
- tomcat session实现原理
- Tomcat实现Session共享
- Tomcat实现session共享
- java数据结构之循环双链表
- 学习java中的单例模式(Singleton)
- TCP慢启动、拥塞控制、快速重传、快速恢复
- Core Data的使用
- Observer pattern
- Tomcat 服务器 Session的实现
- HDU 5699 货物运输
- 将一个正整数分解质因数
- Oracle、PostgreSQL、Sybase数据库导入导出
- VLC学习(1)—— window下SDK使用
- 高级I/O-----dup/dup2
- pull解析
- Spring事务的隔离级别
- 高版本ubuntu安装低版本arm-linux-gcc