• Session会话追踪的实现机制


    前言

             HTTP协议是一个无状态协议,什么是无状态协议呢?  Web应用程序无法区分收到的不同的HTTP请求是否是同一个浏览器发出的。

            在Web应用程序中,Servlet和客户的通信采用“请求/响应”的模式。那服务器又是如何分别不同用户的呢?例如:当一个用户登录成功后,如果他继续访问其他页面,Web程序如何才能识别出该用户身份?   

            为了跟踪用户状态, Servlet容器提供了Session机制用以跟踪用户。服务器可以向浏览器分配一个唯一ID,并以Cookie的形式发送到浏览器,浏览器在后续访问时总是附带此Cookie,这样,服务器就可以识别用户身份。

    什么是Session机制?

            Session相当于程序在服务器上建立的一份客户档案,当程序需要为某个客户端的请求创建一个Session时,服务器首先检查这个客户端的请求里是否包含了一个Session标识(即SessionId),如果已经包含一个sessionId则说明以前已经为此客户创建过Session,服务器就按照SessionId把这个Session检索出来使用。如果客户请求不包含sessionId,会自动获得一个Session ID。并本次响应中返回给客户端保存。

            我们把这种基于唯一ID识别用户身份的机制称为Session。如果用户在一段时间内没有访问服务器,那么Session会自动失效,下次即使带着上次分配的Session ID访问,服务器也认为这是一个新用户,会分配新的Session ID。一次Session会话中往往包含着若干次request请求。


            JavaEE的Servlet机制内建了对Session的支持。当我们需要获取Session时,可以通过request请求对象的getSession()方法。例如;

    HttpSession session=request.getSession();



    服务器识别Session的关键就是依靠一个名为JSESSIONID的Cookie。在Servlet中第一次调用request.getSession()时,Servlet容器自动创建一个Session ID,然后通过一个名为JSESSIONID的Cookie发送给浏览器:

    例如运行如下代码:

    1. @WebServlet("/text_session.do")
    2. public class TextSessionServlet extends HttpServlet {
    3. @Override
    4. protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    5. System.out.println("TextSessionServlet被GET到");
    6. // 第一次在访问Session时,服务器会创建Session
    7. // 并根据Session_ID,创建一个名称为"JSESSIONID"的Cookie,将Session_ID保存在Cookie
    8. // 将该Cookie响应回至浏览器保存
    9. // 接下来的每次发起请求时,客户端浏览器都会在请求中,添加JESSIONID
    10. // 用于服务器确认"身份"
    11. HttpSession session =req.getSession();
    12. System.out.println(session.getId());
    13. }
    14. }

    控制台结果:

     网页请求头所在第一次创建Session返回JSESSIONID:


    Cookie

            实际上,Servlet提供的HttpSession本质上就是通过一个名为JSESSIONID的Cookie来跟踪用户会话的。除了这个名称外,其他名称的Cookie我们可以任意使用。
            创建一个新Cookie时,除了指定名称和值以外,通常需要设置setPath("/"),浏览器根据此前缀决定是否发送Cookie。如果一个Cookie调用了setPath("/user/"),那么浏览器只有在请求以/user/开头的路径时才会附加此Cookie。通过setMaxAge()设置Cookie的有效期,单位为秒,最后通过resp.addCookie()把它添加到响应。
            通过创建Cookie,我们可以实现在客户端浏览器中存储数据的目的,例如保存用户名和密码。在Chrome浏览器中,单个 Cookie的长度不能超过 4069 个字符(包括 name,但不包括 = 号)。
    我们可以在浏览器看到服务器发送的Cookie,以百度为例:

    创建Cookie对象

    1. @WebServlet("/text_cookie.do")
    2. public class TextCookieServlet extends HttpServlet {
    3. @Override
    4. protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    5. //创建cookie对象
    6. Cookie cookie1=new Cookie("phone_number", "12323234545");
    7. Cookie cookie2=new Cookie("name", "xiaoming");
    8. Cookie cookie3=new Cookie("sex", "boy");
    9. Cookie cookie4=new Cookie("height", "188cm");
    10. cookie1.setMaxAge(24*24*60*7);//设置过期时间,单位为秒
    11. cookie2.setMaxAge(24*24*60*7);//设置过期时间,单位为秒
    12. cookie3.setMaxAge(24*24*60*7);//设置过期时间,单位为秒
    13. cookie4.setMaxAge(24*24*60*7);//设置过期时间,单位为秒
    14. //响应
    15. resp.addCookie(cookie1);//添加至响应头
    16. resp.addCookie(cookie2);//添加至响应头
    17. resp.addCookie(cookie3);//添加至响应头
    18. resp.addCookie(cookie4);//添加至响应头
    19. }
    20. }

     

    如果我们要读取Cookie,例如,在TextCookieServlet中,读取Cookie以获取用户设置的语言,可以写一个方法如下:

    1. @WebServlet("/text_get_cookie.do")
    2. public class TextGetCookieServlet extends HttpServlet {
    3. @Override
    4. protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    5. System.out.println("测试获取cookie");
    6. Cookie[] cookies=req.getCookies();
    7. if (cookies!=null) {
    8. for (Cookie cookie : cookies) {
    9. System.out.println(cookie.getName());
    10. System.out.println(cookie.getValue());
    11. System.out.println();
    12. }
    13. }
    14. }
    15. }

    观察控制台: 

     

    所以,读取Cookie主要依靠遍历HttpServletRequest附带的所有Cookie

  • 相关阅读:
    【Rust笔记】Rust与Java交互-JNI模块编写-实践总结
    02 java ---- Android 基础app开发
    编程同步与异步、进程与线程、进程间通信具体分析、线程同步与互斥具体分析、五种io模型具体分析
    Nginx的安全控制
    常见的ssh功能
    (三)组合特征与特征变换 学习简要笔记 #机器学习特征工程 #CDA学习打卡
    [OpenGL教程05 ] glAccum() 函数对累积缓存设置
    vue修改子组件中的el-input的placeholder字体颜色
    计算器(有qt界面)
    基于STM32的u8g2移植以及学习
  • 原文地址:https://blog.csdn.net/w259149/article/details/126482914