zoukankan      html  css  js  c++  java
  • Tomcat中的Session小结

    什么是Session

    对Tomcat而言,Session是一块在服务器开辟的内存空间,其存储结构为ConcurrentHashMap;

     

    Session的目的

    Http协议是一种无状态协议,即每次服务端接收到客户端的请求时,都是一个全新的请求,服务器并不知道客户端的历史请求记录;

    Session的主要目的就是为了弥补Http的无状态特性。简单的说,就是服务器可以利用session存储客户端在同一个会话期间的一些操作记录;

     

    实现机制

    先看两个问题,如下:

    1、服务器如何判断客户端发送过来的请求是属于同一个会话?

    答:用Session id区分,Session id相同的即认为是同一个会话,在Tomcat中Session id用JSESSIONID表示;

    2、服务器、客户端如何获取Session id?Session id在其之间是如何传输的呢?

    答:服务器第一次接收到请求时,开辟了一块Session空间(创建了Session对象),同时生成一个Session id,并通过响应头的Set-Cookie:“JSESSIONID=XXXXXXX”命令,向客户端发送要求设置cookie的响应;

    客户端收到响应后,在本机客户端设置了一个JSESSIONID=XXXXXXX的cookie信息,该cookie的过期时间为浏览器会话结束;

    接下来客户端每次向同一个网站发送请求时,请求头都会带上该cookie信息(包含Session id);

    然后,服务器通过读取请求头中的Cookie信息,获取名称为JSESSIONID的值,得到此次请求的Session id;

    ps:服务器只会在客户端第一次请求响应的时候,在响应头上添加Set-Cookie:“JSESSIONID=XXXXXXX”信息,接下来在同一个会话的第二第三次响应头里,是不会添加Set-Cookie:“JSESSIONID=XXXXXXX”信息的;

    而客户端是会在每次请求头的cookie中带上JSESSIONID信息;

    举个例子:

    以chrome浏览器为例,访问一个基于tomcat服务器的网站的时候,

    浏览器第一次访问服务器,服务器会在响应头添加Set-Cookie:“JSESSIONID=XXXXXXX”信息,要求客户端设置cookie,如下图:

    同时我们也可以在浏览器中找到其存储的sessionid信息,如下图

    接下来,浏览器第二次、第三次...访问服务器,观察其请求头的cookie信息,可以看到JSESSIONID信息存储在cookie里,发送给服务器;且响应头里没有Set-Cookie信息,如下图:

    只要浏览器未关闭,在访问同一个站点的时候,其请求头Cookie中的JSESSIONID都是同一个值,被服务器认为是同一个会话。

     再举个简单的例子加深印象,新建个Web工程,并写一个Servlet,在doGet中添加如下代码,主要做如下工作

    首先,从session中获取key为count的值,累加,存入session,并打印;

    然后,每次从请求中获取打印cookie信息,从响应中获取打印Header的Set-Cookie信息:

    /**
         * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
         */
        protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            
            if(request.getSession().getAttribute("count") == null){
                request.getSession().setAttribute("count", 0);
                response.getWriter().write(0+"");
            }else{
                int a = Integer.parseInt(request.getSession().getAttribute("count").toString());
                request.getSession().setAttribute("count", ++a);
                response.getWriter().write(a+"");
            }
    
            Cookie[] cookies = request.getCookies();
            StringBuffer sb = new StringBuffer();
            if(cookies!=null){
                for(Cookie cookie : cookies){
                    sb.append(cookie.getName()+":"+cookie.getValue()+",");
                }
                sb.deleteCharAt(sb.length()-1);
            }
    
            System.out.println("[第"+(++index)+"次访问]from client request, cookies:" + sb);
            System.out.println("[第"+(index)+"次访问]from server response, header-Set-Cookie:" + response.getHeader("Set-Cookie"));;
        }

    部署到tomcat后,连续访问该servlet,观察控制台输出,如下,客户端第一次访问服务器的时候,在服务端的响应头里添加了JSESSIONID信息,且接下来客户端的每次访问都会带上该JSESSIONID:

    其实这里有一个问题,session劫持

    只要用户知道JSESSIONID,该用户就可以获取到JSESSIONID对应的session内容,还是以上面这个例子为例,

    我先用IE浏览器访问该站点,比如连续访问了5次,此时,session中的count值为:

    查看该会话的Session id,为6A541281A79B24BC290ED3270CF15E32

    接下来打开chrome控制台,将IE浏览器获取过来的JSESSIONID信息(“6A541281A79B24BC290ED3270CF15E32”)写入到cookie中,如下

    接着删除其中的一个,只留下JSESSIONID为“6A541281A79B24BC290ED3270CF15E32”的cookie;

    刷新页面,发现我们从session获取的count值已经变成6了,说明此次chrome浏览器的请求劫持了IE浏览器会话中的session,

    session存在的问题

    • 安全性,session劫持,这个前面已经举过例子了;
    • 增加服务器压力,因为session是直接存储在服务器的内存中的;
    • 如果存在多台服务器的话,还存在session同步问题,当然如果只有一台tomcat服务器的话,也就没有session同步的事情了,然而现在一般的应用都会用到多台tomcat服务器,通过负载均衡,同一个会话有可能会被分配到不同的tomcat服务器,因此很可能出现session不一致问题;解决session同步问题,实际上主要是保证能够抽离出一块共享空间存放session信息,且这块空间不同的tomcat服务器都可以访问到;一般这块共享的空间可以是数据库,或者某台服务器的内存空间,甚至硬盘空间,或者客户端的cookie也是可以的;

    http://www.cnblogs.com/chenpi/p/5434537.html 感谢原文作者

  • 相关阅读:
    2.4 使用vue-cli创建项目/项目打包/发布
    2.3 vue-cli脚手架工具/nodejs
    2.2 vue的devtools、eslint检测问题
    2. es6扩展运算符
    文件json
    函数
    函数不固定参数
    监控日志,加入黑名单
    非空即真
    随机生成手机号,存入文件
  • 原文地址:https://www.cnblogs.com/jiafuwei/p/6066310.html
Copyright © 2011-2022 走看看