• 会话管理Cookie和Session(源码级讲解、超详细)



    1. 会话管理概述

    1.1 为什么需要会话管理

    HTTP是无状态协议

    • 无状态就是不保存状态,即无状态协议(stateless),HTTP协议自身不对请求和响应之间的通信状态进行保存,也就是说,在HTTP协议这个级别,协议对于发送过的请求或者响应都不做持久化处理
    • 简单理解:浏览器发送请求,服务器接收并响应,但是服务器不记录请求是否来自哪个浏览器,服务器没记录浏览器的特征,就是客户端的状态

    1.1.2 会话管理实现的手段

    Cookie和Session配合解决

    • cookie是在客户端保留少量数据的技术,主要通过响应头向客户端响应一些客户端要保留的信息
    • session是在服务端保留更多数据的技术,主要通过HttpSession对象保存一些和客户端相关的信息
    • cookie和session配合记录请求状态

    2 Cookie

    2.1 Cookie概述

    cookie是一种客户端会话技术,cookie由服务端产生,它是服务器存放在浏览器的一小份数据,浏览器以后每次访问该服务器的时候都会将这小份数据携带到服务器去。

    • 服务端创建cookie,将cookie放入响应对象中,Tomcat容器将cookie转化为set-cookie响应头,响应给客户端
    • 客户端在收到cookie的响应头时,在下次请求该服务的资源时,会以cookie请求头的形式携带之前收到的Cookie
    • cookie是一种键值对格式的数据,从tomcat8.5开始可以保存中文,但是不推荐
    • 由于cookie是存储于客户端的数据,比较容易暴露,一般不存储一些敏感或者影响安全的数据

    原理图:
    在这里插入图片描述

    应用场景举例:

    记录用户名:

    当我们在用户名的输入框中输入完用户名后,浏览器记录用户名,下一次再访问登录页面时,用户名自动填充到用户名的输入框.

    2.2 Cookie的使用

    servletA向响应中增加Cookie

    @WebServlet("/servletA")
    public class ServletA extends HttpServlet {
        @Override
        protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            // 创建Cookie
            Cookie cookie1 =new Cookie("c1","c1_message");
            Cookie cookie2 =new Cookie("c2","c2_message");
            // 将cookie放入响应对象
            resp.addCookie(cookie1);
            resp.addCookie(cookie2);
        }
    }
    

    servletB从请求中读取Cookie

    @WebServlet("/servletB")
    public class ServletB extends HttpServlet {
        @Override
        protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            //获取请求中的cookie
            Cookie[] cookies = req.getCookies();
            //迭代cookies数组
            if (null != cookies && cookies.length!= 0) {
                for (Cookie cookie : cookies) {
                    System.out.println(cookie.getName()+":"+cookie.getValue());
                }
            }
        }
    }
    

    2.3 Cookie的时效性

    默认情况下Cookie的有效期是一次会话范围内,我们可以通过cookie的setMaxAge()方法让Cookie持久化保存到浏览器上

    • 会话级Cookie
      • 服务器端并没有明确指定Cookie的存在时间
      • 在浏览器端,Cookie数据存在于内存中
      • 只要浏览器还开着,Cookie数据就一直都在
      • 浏览器关闭,内存中的Cookie数据就会被释放
    • 持久化Cookie
      • 服务器端明确设置了Cookie的存在时间
      • 在浏览器端,Cookie数据会被保存到硬盘上
      • Cookie在硬盘上存在的时间根据服务器端限定的时间来管控,不受浏览器关闭的影响
      • 持久化Cookie到达了预设的时间会被释放

    cookie.setMaxAge(int expiry)参数单位是秒,表示cookie的持久化时间,如果设置参数为0,表示将浏览器中保存的该cookie删除

    • servletA设置一个Cookie为持久化cookie
    @WebServlet("/servletA")
    public class ServletA extends HttpServlet {
        @Override
        protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            // 创建Cookie
            Cookie cookie1 =new Cookie("c1","c1_message");
            cookie1.setMaxAge(60);
            Cookie cookie2 =new Cookie("c2","c2_message");
            // 将cookie放入响应对象
            resp.addCookie(cookie1);
            resp.addCookie(cookie2);
        }
    }
    
    • servletB接收Cookie,浏览器中间发生一次重启再请求servletB测试
    @WebServlet("/servletB")
    public class ServletB extends HttpServlet {
        @Override
        protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            //获取请求中的cookie
            Cookie[] cookies = req.getCookies();
            //迭代cookies数组
            if (null != cookies && cookies.length!= 0) {
                for (Cookie cookie : cookies) {
                    System.out.println(cookie.getName()+":"+cookie.getValue());
                }
            }
        }
    }
    

    2.4 Cookie的提交路径

    访问互联网资源时不能每次都需要把所有Cookie带上。访问不同的资源时,可以携带不同的cookie,我们可以通过cookie的setPath(String path) 对cookie的路径进行设置

    • 从ServletA中获取cookie
    public class ServletA extends HttpServlet {
        @Override
        protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            // 创建Cookie
            Cookie cookie1 =new Cookie("c1","c1_message");
            // 设置cookie的提交路径
            cookie1.setPath("/web03_war_exploded/servletB");
            Cookie cookie2 =new Cookie("c2","c2_message");
            // 将cookie放入响应对象
            resp.addCookie(cookie1);
            resp.addCookie(cookie2);
        }
    }
    
    

    3. Session

    3.1 HttpSession概述

    HttpSession是一种保留更多信息在服务端的一种技术,服务器会为每一个客户端开辟一块内存空间,即session对象. 客户端在发送请求时,都可以使用自己的session. 这样服务端就可以通过session来记录某个客户端的状态了

    • 服务端在为客户端创建session时,会同时将session对象的id,即JSESSIONID以cookie的形式放入响应对象
    • 后端创建完session后,客户端会收到一个特殊的cookie,叫做JSESSIONID
    • 客户端下一次请求时携带JSESSIONID,后端收到后,根据JSESSIONID找到对应的session对象
    • 通过该机制,服务端通过session就可以存储一些专门针对某个客户端的信息了
    • session也是域对象(后续详细讲解)

    原理图如下

    在这里插入图片描述

    应用场景

    1. 记录用户的登录状态

      用户登录后,将用户的账号等敏感信息存入session

    2. 记录用户操作的历史

      例如记录用户的访问痕迹,用户的购物车信息等临时性的信息

    3.2 HttpSession的使用

    用户提交form表单到ServletA,携带用户名,ServletA获取session 将用户名存到Session,用户再请求其他任意Servlet,获取之间存储的用户

    • 定义表单页,提交用户名,提交后
        <form action="servletA" method="post">
            用户名:
            <input type="text" name="username">
            <input type="submit" value="提交">
        form>
    
    • 定义ServletA,将用户名存入session
    @WebServlet("/servletA")
    public class ServletA extends HttpServlet {
        @Override
        protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            // 获取请求中的参数
            String username = req.getParameter("username");
            // 获取session对象
            HttpSession session = req.getSession();
             // 获取Session的ID
            String jSessionId = session.getId();
            System.out.println(jSessionId);
            // 判断session是不是新创建的session
            boolean isNew = session.isNew();
            System.out.println(isNew);
            // 向session对象中存入数据
            session.setAttribute("username",username);
    
        }
    }
    
    • 响应中收到了一个JSESSIONID的cookie

    • 定义其他Servlet,从session中读取用户名

    @WebServlet("/servletB")
    public class ServletB extends HttpServlet {
        @Override
        protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            // 获取session对象
            HttpSession session = req.getSession();
             // 获取Session的ID
            String jSessionId = session.getId();
            System.out.println(jSessionId);
            // 判断session是不是新创建的session
            boolean isNew = session.isNew();
            System.out.println(isNew);
            // 从session中取出数据
            String username = (String)session.getAttribute("username");
            System.out.println(username);
        }
    }
    
    • 请求中携带了一个JSESSIONID的cookie

    3.3 HttpSession时效性

    为什么要设置session的时效

    • 用户量很大之后,Session对象相应的也要创建很多。如果一味创建不释放,那么服务器端的内存迟早要被耗尽。
    • 客户端关闭行为无法被服务端直接侦测,或者客户端较长时间不操作也经常出现,类似这些的情况,就需要对session的时限进行设置了

    默认的session最大闲置时间(两次使用同一个session中的间隔时间) 在tomcat/conf/web.xml配置为30分钟

    我们可以自己在当前项目的web.xml对最大闲置时间进行重新设定

    也可以通过HttpSession的API 对最大闲置时间进行设定

    // 设置最大闲置时间
    session.setMaxInactiveInterval(60);
    

    也可以直接让session失效

    // 直接让session失效
    session.invalidate();
    
  • 相关阅读:
    关于前后端分离的项目打包方案docker
    预约按摩app小程序开发搭建;
    Git(七).git 文件夹瘦身,GitLab 永久删除文件
    Polygon zkEVM Prover
    机械原理-试题及答案
    GIN框架路由的实现原理
    python内存泄漏浅析
    请求一下子太多了,数据库危
    设计模式day13
    基于微信小程序的自习室系统设计与实现,可作为毕业设计
  • 原文地址:https://blog.csdn.net/2301_77193348/article/details/141036384