`
com_xpp
  • 浏览: 354177 次
社区版块
存档分类
最新评论

Session那些事(一)

    博客分类:
  • java
阅读更多

     前一段时间做一个应用的客户端时,涉及到用户权限的问题,所以用到了Session,遇到一些问题,网上找了各位大神的一些资料,今天汇总到这,以便以后复习。

 

1.Session

由于HTTP协议连接的无状态性,才使得session的不得已而产生。既然Web应用并不了解有关同一用户以前请求的信息,那么解决这个问题的一个办法是使用Servlet/JSP容器提供的会话跟踪功能,Servlet API规范定义了一个简单的HttpSession接口,通过它我们可以方便地实现会话跟踪。

 HttpSession接口提供了存储和返回标准会话属性的方法。标准会话属性如会话标识符、应用数据等,都以“名字-值”对的形式保存在服务器端。也就是说,HttpSession接口提供了一种把对象保存到内存、在同一用户的后继请求中提取这些对象的标准办法。在会话中保存数据的方法是setAttribute(String s, Object o),从会话提取原来所保存对象的方法是getAttribute(String s)。

在服务器端,每当新用户请求了一个使用HttpSession对象的JSP页面,Servlet、JSP容器除了发回应答页面外,它还要以cookie的形式向浏览器发送一个特殊数字,即“绘画标识符”,它是一个唯一的用户标示符,浏览器在请求session时,服务器会先得到它的sessionId,在做处理。
 会话标识符以Cookie的形式在服务器和浏览器组件传送,标准会话属性在服务器端也是以会话的形式存在,并且这个Cookie的生命周期只是临时的,即会话结束后就自动消失,没有为它指定固定的生命周期,因此可以说session是基于Cookie的技术。另外,如果客户端不支持Cookie,运用URL重写机制来保证会话标识回服务器。


2.session机制的实现:

 
(1.)session机制是一种服务器端的机制,
用来在无状态的HTTP协议下越过多个请求页面来维持状态和识别用户。
当程序需要为某个客户端的请求创建一个session的时候,
服务器首先检查这个客户端的请求里是否已包含了一个session标识。

这个标识称为session id,
如果已包含一个session id则说明以前已经为此客户端创建过session,
服务器就按照session id把这个session检索出来使用,
若没有创建过,则创建一个新的Session。

那么这个session是什么时候创建的呢?
之前一直错误地理解为:
当用户向服务器发起请求时,这个session便会立刻建立起来,
但实际上却根本不是这样。

在Servlet中,你肯定用过下面这句话,

HttpSession session = request.getSession();如果当前没有session,则会立刻建立一个session;
如果有session则返回当前session。

这句话和

HttpSession session = request.getSession(true);的效果是一样的。

但是如果你写成

HttpSession session = request.getSession(false);则不会自动建立session。
若当前没有session,你所得到的seesion只会是一个null。

总结:
session不是一打开网站就会立刻建立。
它的建立需要基于下面两个条件中的任意一个:

   a:在servlet中手动调用

HttpSession session = request.getSession();或者

HttpSession session = request.getSession(true);2:jsp中没有写
(默认情况下它是的)

如果两个条件同时都不满足,那么你建立的只是一个无seesion的连接。

 


(2.) session机制是一种服务器端的机制,服务器使用一种类似于散列表的结构(也可能就是使用散列表)来保存信息。 
      当程序需要为某个客户端的请求创建一个session的时候,

第一步: 
      服务器首先检查这个客户端的请求里是否已包含了一个session标识 - 称为session id, 
此时就是两种可能,客户机有session id或者没有session id

第二步: 
      如果已包含一个session id则说明以前已经为此客户端创建过session,服务器就按照session id把这个session检索出来使用(如果检索不到,可能会新建一个) 
      如果客户端请求不包含session id,则为此客户端创建一个session并且生成一个与此session相关联的session id 
(session id的值应该是一个既不会重复,又不容易被找到规律以仿造的字符串,这个session id将被在本次响应中返回给客户端保存。)

三、保存session id 的方法 
一)、cookie: 
二)、URL重写: 
cookie可以被人为的禁止,必须有其他机制以便在cookie被禁止时仍然能够把session id传递回服务器。经常被使用的一种技术叫做URL重写,就是把session id直接附加在URL路径

的后面。


3.session与Cookie的实现原理

Session 与 Cookie 的作用都是为了保持访问用户与后端服务器的交互状态。它们有各自的优点也有各自的缺陷。然而具有讽刺意味的是它们优点和它们的使用场景又是矛盾的,例如使用 Cookie 来传递信息时,随着 Cookie 个数的增多和访问量的增加,它占用的网络带宽也很大,试想假如 Cookie 占用 200 个字节,如果一天的 PV 有几亿的时候,它要占用多少带宽。所以大访问量的时候希望用 Session,但是 Session 的致命弱点是不容易在多台服务器之间共享,所以这也限制了 Session 的使用。

不管 Session 和 Cookie 有什么不足,我们还是要用它们。下面详细讲一下,Session 如何基于 Cookie 来工作。实际上有三种方式能可以让 Session 正常工作:

1.基于 URL Path Parameter,默认就支持
2.基于 Cookie,如果你没有修改 Context 容器个 cookies 标识的话,默认也是支持的
3.基于 SSL,默认不支持,只有 connector.getAttribute("SSLEnabled") 为 TRUE 时才支持
第一种情况下,当浏览器不支持 Cookie 功能时,浏览器会将用户的 SessionCookieName 重写到用户请求的 URL 参数中,它的传递格式如 /path/Servlet;name=value;name2=value2? Name3=value3,其中“Servlet;”后面的 K-V 对就是要传递的 Path Parameters,服务器会从这个 Path Parameters 中拿到用户配置的 SessionCookieName。关于这个 SessionCookieName,如果你在 web.xml 中配置 session-config 配置项的话,其 cookie-config 下的 name 属性就是这个 SessionCookieName 值,如果你没有配置 session-config 配置项,默认的 SessionCookieName 就是大家熟悉的“JSESSIONID”。接着 Request 根据这个 SessionCookieName 到 Parameters 拿到 Session ID 并设置到 request.setRequestedSessionId 中。

请注意如果客户端也支持 Cookie 的话,Tomcat 仍然会解析 Cookie 中的 Session ID,并会覆盖 URL 中的 Session ID。

如果是第三种情况的话将会根据 javax.servlet.request.ssl_session 属性值设置 Session ID。

有了 Session ID 服务器端就可以创建 HttpSession 对象了,第一次触发是通过 request. getSession() 方法,如果当前的 Session ID 还没有对应的 HttpSession 对象那么就创

建一个新的,并将这个对象加到 org.apache.catalina. Manager 的 sessions 容器中保存,Manager 类将管理所有 Session 的生命周期,Session 过期将被回收,服务器关闭,

Session 将被序列化到磁盘等。只要这个 HttpSession 对象存在,用户就可以根据 Session ID 来获取到这个对象,也就达到了状态的保持。

 

还有一点与 Session 关联的 Cookie 与其它 Cookie 没有什么不同,这个配置的配置可以通过 web.xml 中的 session-config 配置项来指定。


4.session中的一些问题
    (1)、session在何时被创建

  一个常见的误解是以为session在有客户端访问时就被创建,然而事实是直到某server端程序调用 HttpServletRequest.getSession(true)这样的语句时才被创建,注意如果JSP没有显示的使用 <%@pagesession="false"%> 关闭session,则JSP文件在编译成Servlet时将会自动加上这样一条语句HttpSession session = HttpServletRequest.getSession(true);这也是JSP中隐含的session对象的来历。

  由于session会消耗内存资源,因此,如果不打算使用session,应该在所有的JSP中关闭它。

 (2)、session何时被删除

  综合前面的讨论,session在下列情况下被删除a.程序调用HttpSession.invalidate();或b.距离上一次收到客户端发送的session id时间间隔超过了session的超时设置;或c.服务器进程被停止(非持久session)

 (3)、如何做到在浏览器关闭时删除session

  严格的讲,做不到这一点。可以做一点努力的办法是在所有的客户端页面里使用网页特效代码window.onclose来监视浏览器的关闭 动作,然后向服务器发送一个请求来删

除session。但是对于浏览器崩溃或者强行杀死进程这些非常规手段仍然无能为力。

 (4)、有个HttpSessionListener是怎么回事

  你可以创建这样的listener去监控session的创建和销毁事件,使得在发生这样的事件时你可以做一些相应的工作。注意是 session的创建和销毁动作触发listener,而不是相反。类似的与HttpSession有关的listener还有 HttpSessionBindingListener,HttpSessionActivationListener和 HttpSessionAttributeListener。

 (5)、存放在session中的对象必须是可序列化的吗

  不是必需的。要求对象可序列化只是为了session能够在集群中被复制或者能够持久保存或者在必要时server能够暂时把session交换出内 存。在Weblogic Server的session中放置一个不可序列化的对象在控制台上会收到一个警告。我所用过的某个iPlanet版本如果session中有不可序列化 的对象,在session销毁时会有一个Exception,很奇怪。

 (6.)、如何才能正确的应付客户端禁止cookie的可能性

  对所有的URL使用URL重写,包括超链接,form的action,和重定向的URL,具体做法参见[6]http://e-docs.bea.com/wls/docs70/webapp/sessions.html#100770

 (7.)、开两个浏览器窗口访问应用程序会使用同一个session还是不同的session

  参见第三小节对cookie的讨论,对session来说是只认id不认人,因此不同的浏览器,不同的窗口打开方式以及不同的cookie存储方式都会对这个问题的答案有影响。

    (8.)、如何防止用户打开两个浏览器窗口操作导致的session混乱

  这个问题与防止表单多次提交是类似的,可以通过设置客户端的令牌来解决。就是在服务器每次生成一个不同的id返回给客户端,同时保存在 session里,客户端提交表单时必须把这个id也返回服务器,程序首先比较返回的id与保存在session里的值是否一致,如果不一致则说明本次操 作已经被提交过了。可以参看《J2EE核心模式》关于表示层模式的部分。需要注意的是对于使用javascript window.open打开的窗口,一般不设置这个id,或者使用单独的id,以防主窗口无法操作,建议不要再window.open打开的窗口里做修改 操作,这样就可以不用设置。

      (9.)、为什么在Weblogic Server中改变session的值后要重新调用一次session.setValue做这个动作主要是为了在集群环境中提示Weblogic Server session中的值发生了改变,需要向其他服务器进程复制新的session值。

 (10)、为什么session不见了

  排除session正常失效的因素之外,服务器本身的可能性应该是微乎其微的,虽然笔者在iPlanet6SP1加若干补丁的Solaris版本上倒 也遇到过;浏览器插件的可能性次之,笔者也遇到过3721插件造成的问题;理论上防火墙或者代理服务器在cookie处理上也有可能会出现问题。

  出现这一问题的大部分原因都是程序的错误,最常见的就是在一个应用程序中去访问另外一个应用程序。

39
2
分享到:
评论
20 楼 jacklujuneye 2015-10-22  
19 楼 boblee2010 2013-04-17  
比如:登录的时候,如果不用session,那应该怎么做呢?大家都会怎么弄呢?
18 楼 liguocai2009 2012-06-12  
steven19880224 写道
dwbin 写道
不错,不过如果做电子商务的话使用session会不会有什么问题啊?比如购物车的物品之类的?如果大量用户在不同domain的站点之间进行操作,这个同步的压力会蛮大的吧?

购物车一般放在数据库零时表里面。放在session里面不安全。

1 为什么会有同步的问题?一个用户一个session怎么会有同步的问题?
2 为什么放到session会不安全?
17 楼 w156445045 2012-06-09  
一直使用session 不过没考虑这么多~
16 楼 com_xpp 2012-06-09  
不错,不过如果做电子商务的话使用session会不会有什么问题啊?比如购物车的物品之类的?如果大量用户在不同domain的站点之间进行操作,这个同步的压力会蛮大的吧?
15 楼 com_xpp 2012-06-09  
不错,不过如果做电子商务的话使用session会不会有什么问题啊?比如购物车的物品之类的?如果大量用户在不同domain的站点之间进行操作,这个同步的压力会蛮大的吧?
14 楼 s10008121y 2012-06-08  
=。=。=。=不错
13 楼 luccs624061082 2012-06-08  
1111111111111111111111111111111111111111111111111111111111111112222222222222222222222222
12 楼 luccs624061082 2012-06-08  
1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111112222222
11 楼 maimode 2012-06-08  
嗯,受益了,以前总以为session是http协议中的呢
10 楼 gearever 2012-06-08  
session机制可以看一下我的博客
http://gearever.iteye.com/blog/1546423
9 楼 lintghi 2012-06-07  
8 楼 hyanqing1 2012-06-07  
你好,你这UML图是用什么工具画的,蛮漂亮的,正在找UML工具呢
7 楼 sumuu 2012-06-07  
dwbin 写道
不错,不过如果做电子商务的话使用session会不会有什么问题啊?比如购物车的物品之类的?如果大量用户在不同domain的站点之间进行操作,这个同步的压力会蛮大的吧?

购物车的话用cookie或者数据库零时表好点。
6 楼 yzongjie 2012-06-07  
很好,有时间再了解一下 session 服务器,就全面了
5 楼 zhangjunbao 2012-06-07  
写的不错!
4 楼 zhouhongqiang2010 2012-06-07  
session在服务器之间不能共享。现在好多都是自己实现一个session,用缓存服务器记录要放到session中的对象。
3 楼 steven19880224 2012-06-07  
dwbin 写道
不错,不过如果做电子商务的话使用session会不会有什么问题啊?比如购物车的物品之类的?如果大量用户在不同domain的站点之间进行操作,这个同步的压力会蛮大的吧?

购物车一般放在数据库零时表里面。放在session里面不安全。
2 楼 aijuans 2012-06-07  
很好,非常好.
1 楼 dwbin 2012-06-07  
不错,不过如果做电子商务的话使用session会不会有什么问题啊?比如购物车的物品之类的?如果大量用户在不同domain的站点之间进行操作,这个同步的压力会蛮大的吧?

相关推荐

    SESSION购物车SESSION购物车SESSION购物车

    SESSION购物车SESSION购物车SESSION购物车SESSION购物车SESSION购物车SESSION购物车SESSION购物车

    一个服务器搭多个tomcat导致session丢失,或者同一个IP不同端口,多个应用的session会冲突解决方法

    一个服务器上搭建了多个tomcat或者weblogic,端口不一样,同时启动访问时session丢失。如:A,B两个服务,在浏览器中登录访问A后,当前打开的浏览器上在开一个选项卡访问B服务后,回过来点击访问A时session丢失,...

    一篇优秀Session讲解

    session讲解,帮助你重新认识session

    tomcat修改sessionId

    tomcat修改sessionId,同一台服务器部署多个tomcat需要修改sessionId,否则会出现session冲突的问题

    分布式解决session共享方案一

    分布式解决session共享方案一,可参考

    WebService中Session的使用.zip

    对于Web Service,每个方法的调用都会启动一个Session,可以用下面的方法来使多个调用在同一个Session里 CWSSyscfg cwsCfg = new CWSSyscfg(); cwsCfg.CookieContainer = new System.Net.CookieContainer(); ...

    WEB Session 分布式处理方案

    购物车分布式Session处理方案,一个用户的分布式的购物车在集群分布式的情况下怎么处理解决Session共享的问题

    在ASP.NET中,设置Session的过期时间的方法

    方法一:  在后台应用程序中设置:Session.Timeout = 1;  注意:1、此方法可以设置在一个... 您可能感兴趣的文章:php 如何设置一个严格控制过期时间的sessionjava设置session过期时间的实现方法php中实现精确设置se

    《session详解》

    session,中文经常翻译为会话,其本来的含义是指有始有终的一系列动作/消息,比如打电话时从拿起电话拨号到挂断电话这中间的一系列过程可以称之为一个session。 session在WEB技术中占有非常重要的份量。由于网页是一...

    数据操作session获取的一个简单实例

    利用的是一个JSP页面 通过表单验证后进行数据库操作并用session

    PHP 一个SESSION 购物车类

    用PHP写的购物车类,实现了 放入商品 修改数量 删除商品 显示购物车信息的功能.只用一个session就实现了 代码比较容易读懂,适合新手学习!...注意:有一个bug,最后一个del_cart()方法要先session_start(); 忘记加了!

    报表session与应用session常识普及

    报表集成到项目中可能会有一个疑问就是系统应用和报表应用在一个web服务器下,那系统session和报表session是不是一个session呢?如果不是那会不会有冲突呢?

    同浏览器不同窗口不同用户Session问题

    正对java Web项目,同浏览器同时打开两个登录窗口(不同Tag),用不同用户登录,为避免使用同一个Session,需要使用这段代码。否则先登录的用户的Session会变成后登录用户的Session.相关系统使用权限也会变。

    Session-JavaWeb专题

    本课程系统地讲解了SESSION这个知识点,主要讲解了Session的概念,它是如何产生,如何工作,如何存放和如何消亡的,以及Session在JavaWeb中的体现和操作,在最后用一个小例子来演示了如何通过Servlet来操作Session。...

    MSM--memcached session manager(memcached+tomcat7共享session所需jar包)

    MSM--memcached session manager是一个高可用的Tomcat session共享解决方案,除了可以从本机内存快速读取Session信息(仅针对黏性Session)外,同时可使用memcached存取Session,以实现高可用。对于非黏性Session,...

    常用跨域共用session的是登录模块

    常用跨域共用session的是登录模块,我相信很多开发的朋友的都遇到过,只需要一个地方登录,相关联的网站也是处于登录状态。两种情况:一种9streets.cn和a.9streets.cn之间,另一种是a.com b.com之间,这几天总结了...

    asp.net中使用session 实现的一个购物车

    本资源是用session实现的一个购物车,是用链表和session实现的购物车,希望对您有所帮助

    基于spring redis的shiro session共享

    shiro 框架没有用tomcat的session,而是重新实现了一套。所以系统一旦引入shiro后,采用传统的tomcat session共享机制是无效的,必须采用面向shiro 的session共享。 网上针对“shiro session共享”的文章比较多,...

    一个关于Session的小demo

    这是一个关于Session的小demo,是一初学Jsp的学生做的,适合初学者使用。

    通过HttpURLConnection获取SESSIONID

    //参数是a=""&b=""这样拼接的一个串 out.flush(); out.close(); out.write(parameters.getBytes(),0,parameters.getBytes().length); InputStream in = hc.getInputStream(); InputStreamReader ...

Global site tag (gtag.js) - Google Analytics