0%

session和cookie

  • session+cookie,做web开发必须知道的东西

5.1 实现用户登录功能

  • 实现登录功能:

    • 步骤1:数据库当中添加一个用户表:t_user
      • t_user 表当中存储的是用户的登录信息,最基本的包括:登录的用户名和登录的密码。
      • 密码一般在数据库表当中存储的是密文,一般不以明文的形式存储。
      • 向 t_user 表中插入用户的数据。
    • 步骤2:再实现一个登录页面。
      • 登录页面上应该有一个登录的表单,有用户名和密码的输入框。
      • 用户点击登录,提交表单,提交用户名和密码,以 post 方式提交。
    • 步骤3:后台要有一个对应的 Servlet 来处理登录的请求。
      • 登录成功:跳转到部门列表页面。
      • 登录失败:跳转到失败的页面。
  • 登录功能实现了,目前存在的最大的问题:

    • 这个登录功能目前只是一个摆设,没有任何作用。只要用户知道后端的请求路径,照样可以在不登录的情况下访问。
    • 这个登录没有真正起到拦截的作用。怎么解决? -> 使用 session 机制。

5.2 ★★★web应用的session机制

  • 什么是会话?

    • 会话对应的英语单词:session。

    • 用户打开浏览器,进行一系列操作,然后最终将浏览器关闭,这个整个过程叫做:一次会话。

      会话在服务器端也有一个对应的 java 对象,这个 java 对象叫做:session

    • 什么是一次请求:用户在浏览器上点击了一下,然后到页面停下来,可以粗略认为是一次请求。

      请求对应的服务器端的 java 对象是:request

    • request 和 session 都是服务器端的 java 对象,都在 JVM 中。

      • request 对象代表了一次请求,一次请求对应一个 request 对象,两次请求就会对应两个不同的 request 对象。
      • session 对象代表了一次会话,一次会话对应一个 session 对象。
    • 一个会话当中包含多次请求(一次会话对应 N 次请求)

  • 在 java 的 servlet 规范当中,session 对应的类名:HttpSession(jarkata.servlet.http.HttpSession)

    session 机制属于 B/S 结构的一部分,如果使用 php 语言开发 WEB 项目,同样也是有 session 这种机制的,session 机制实际上是一个规范,不同的语言对这种会话机制都有实现。

  • session 对象最主要的作用是:保存会话状态(用户登录成功了,这是一种登录成功的状态,你怎么把登录成功的状态一直保存下来呢?使用 session 对象可以保留会话状态)。

    • 为什么需要 session 对象来保存会话状态呢?
      • 因为 HTTP 协议是一种无状态协议。
      • 什么是无状态:请求的时候,B 和 S 是连接的,但是请求结束之后,连接就断了。可以理解为,在请求时,浏览器和服务器之间会建立管道,进行数据的传输,一但数据传输完成,那么这条管道就会断开。为什么要这么做?HTTP 协议为什么要设计成这样?
        • 因为这样的无状态协议,可以降低服务器的压力。请求的瞬间是连接的,请求结束之后,连接断开,这样服务器压力小。
      • 只要 B 和 S 断开了,那么关闭浏览器这个动作,服务器知道吗?
        • 不知道,服务器是不知道浏览器关闭的。
  • 张三打开一个浏览器 A,李四打开一个浏览器 B,访问服务器之后,在服务器端会生成:

    • 张三专属的 session 对象。
    • 李四专属的 session 对象。
  • 为什么不使用 request 对象保存会话状态?为什么不使用 ServletContext 对象保存会话状态?

    • 比如用request.setAttribute()存,用request.getAttribute()取。

      类似的,ServletContext 也有这两个方法。

      • 因为 request 对象的生命周期太短,request 是一次请求对应一个 request 对象,请求结束后 request 对象就销毁了。
      • 因为 ServletContext 对象的域太大,ServletContext 对象是服务器启动的时候创建,服务器关闭的时候销毁,这个 ServletContext 对象只有一个,如果将会话状态放在 ServletContext 对象中,那所有用户都共享保存的会话状态了。
    • request 请求域(HttpServletRequest)、session 会话域(HttpSession)、application 应用域(ServletContext)。

      • 这三个域的大小:request < session < application

★★★session的实现原理

  • 思考一下:session 对象的实现原理。

    • HttpSession session = request.getSession();
    • 这行代码很神奇,张三访问的时候获取的 session 对象就是张三的,李四访问的时候获取的 session 对象就是李四的。
  • session 的实现原理:

    ![](../../../../../Running Noob/计算机/Typora笔记/笔记-git仓库/JavaWeb-notebook/session+cookie/session实现原理.png)

    1. session 对象是存储在服务器端的

    2. 一个 session 对象对应一个会话。一次会话中包含多次请求。

    3. session 对象怎么获取?

      • HttpSession session = request.getSession();

        从 Web 服务器当中获取当前的 session 对象,如果 session 对象没有,则新建

      • HttpSession session = request.getSession(false);

        从 Web 服务器当中获取当前的 session 对象,如果 session 对象没有,并不会新建,返回 null。

    4. session 的实现原理:

      • 在 web 服务器中有一个 session 列表,类以于 map 集合。

        这个 map 集合的 key 存储的是 sessionid,value 存储的是对应的 session 对象。

      • 用户发送第一次请求的时候:服务器会创建一个新的 session 对象,同时给 session 对象生成一个 id,然后 web 服务器会将 session 的 id 发送给浏览器,浏览器将 session 的 id 保存在浏览器的缓存中

        • 在第一次请求时,服务器的响应中有 JSESSIONID=xxxxxx,这个是cookie 的形式保存在浏览器的内存中的,只要浏览器关闭了,这个 cookie 就没有了。

        用户发送第二次请求的时候:会自动将浏览器缓存中的 sessionid 自动发送给服务器,服务器获取到 sessionid,然后从 session 列表中查找到对应的 session 对象。

    5. 为什么关闭浏览器,会话结束?

      • 关闭浏览器之后,浏览器中保存的 sessionid 消失,下次重新打开浏览器之后,浏览器缓存中没有这个 sessionid,自然找不到服务器中对应的 session 对象,session 对象找不到等同于会话结束

        注意:此时并不代表服务器端相应的 session 对象被销毁

    6. session 对象什么时候被销毁?

      • 一种销毁:是超时销毁
      • 一种销毁:是手动销毁

      浏览器关闭的时候,服务器是不知道的,服务器无法监测到浏览器关闭了(因为 HTTP 是无状态协议),所以 session 的销毁要依靠 “session 超时机制”。但也有一种可能,系统提供了“安全退出”,用户可以点击这个按钮,这样服务器就知道你退出了,然后服务器会自动销毁 session 对象。

      • 设置 session 对象的超时销毁的配置:

        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        14
        <?xml version="1.0" encoding="UTF-8"?>
        <web-app xmlns="https://jakarta.ee/xml/ns/jakartaee"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee https://jakarta.ee/xml/ns/jakartaee/web-app_6_0.xsd"
        version="6.0">

        <!-- session的超时时长为30分钟 -->
        <!-- 如果30分钟过去了,session对象仍然没有被访问,那么session对象会被销毁 -->
        <!-- 默认值为30 -->
        <session-config>
        <session-timeout>30</session-timeout>
        </session-config>

        </web-app>
思考
  • cookie 禁用了,session 还能找到吗?
    • cookie 禁用是什么意思?
      • 服务器正常发送 cookie 给浏览器,但是浏览器不要了,拒收了,并不是服务器不发了。
    • 找不到 session 了,每一次请求都会在服务器创建新的 session 对象,服务器没有收到浏览器的 sessionid,无法查找之前创建的 session 对象。
    • cookie 禁用了,session 机制还能实现吗?

目前所学的域对象

  • 总结一下到目前为止我们所了解的域对象:

    • request(对应的类名:HttpServletRequest

      • 请求域(请求级别的)
    • session(对应的类名:HttpSession

      • 会话域(用户级别的)
    • application(对应的类名:ServletContext

      • 应用域(项目级别的,所有用户共享的)
    • 这三个域对象的大小关系

      • request < session < application
    • 他们三个域对象都有以下三个公共的方法:

      • setAttribute(向域当中绑定数据)

      • getAttribute(从域当中获取数据)

      • removeAttribute(删除域当中的数据)

    • 使用原则:尽量使用小的域。

session改造oa项目

  • session 掌握之后,我们怎么解决 oa 项目中的登录问题,怎么能让登录起作用,而不是“只要用户知道后端的请求路径,照样可以在不登录的情况下访问”。

    • 登录成功之后,可以将用户的登录信息存储到 session 当中,也就是说 session 中如果有用户的信息就代表用户登录成功了;session 中没有用户信息,表示用户没有登录过,则跳转到登录页面。

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      protected void doGet(HttpServletRequest request, HttpServletResponse response)
      throws ServletException, IOException {
      // 获取session对象,如果session对象不存在,则返回null
      HttpSession session = request.getSession(false);
      if (session != null && session.getAttribute("username") != null) { // session条件判断
      // 这里写的比较简陋,完整的应该是如果条件成立,
      // 就会执行数据相关的crud操作,然后带着数据跳转到相应的页面
      // 所以如果直接访问 ip:port/xxx/xxx.jsp 是不会显示数据的
      response.sendRedirect(request.getContextPath() + "/success.jsp");
      } else {
      response.sendRedirect(request.getContextPath());
      }
      }
  • JSP 的九大内置对象中有 session,所以一访问 index.jsp 页面就会创建一个相应的 session 会话对象。而不是按照我们希望的那样,在用户登录成功以后,才创建 session 对象。

    所以如果要让在访问 index.jsp 页面的时候不生成 session 对象,同时在该页面中也不能使用 session 内置对象:

    1
    2
    <%-- 访问JSP页面时不生成session对象,同时在该JSP页面中也不能使用session内置对象 --%>
    <%@page session = "false" %>
  • 销毁 session 对象:

    1
    session.invalidate();

5.3 ★★★Cookie

cookie的理论基础

  • session 的实现原理中,每一个 session 对象都会关联一个 sessionid,例如:

    • JSESSIONID=41C481F0224664BDB28E95081D23D5B8

      以上的这个键值对数据其实就是 cookie 对象

      对于 session 关联的 cookie 来说,这个 cookie 是被保存在浏览器的 “运行内存” 当中。只要浏览器不关闭,用户再次发送请求的时候,会自动将运行内存中的 cookie 发送给服务器。

      • 例如,这个 Cookie:JSESSIONID=41C481F0224664BDB28E95081D23D5B8 就会再次发送给服务器。服务器就是根据 41C481F0224664BDB28E95081D23D5B8 这个值来找到对应的 session 对象的。
  • cookie 怎么生成?cookie 保存在什么地方?cookie 有啥用?浏览器什么时候会发送 cookie,发送哪些 cookie 给服务器?

    • cookie 怎么生成?

      • Cookie 是由服务器生成并发送给客户端的小型数据文件。
        • 在 Java 程序中通过 response.addCookie(cookie); ,服务器将 cookie 发送给浏览器。
    • cookie 保存在什么地方?

      cookie 最终是保存在浏览器客户端上的。

      • 可以保存在运行内存中(浏览器只要关闭 cookie 就消失了)。
      • 也可以保存在硬盘文件中(永久保存)。

      关于 cookie 的有效时间及保存方式:

      • 怎么用 java 设置 cookie 的有效时间:
        • cookie.setMaxAge(60 * 60); 设置 cookie 在一小时之后失效。
      • 没有设置有效时间:默认保存在浏览器的运行内存中,浏览器关闭则 cookie 消失
      • 只要设置 cookie 的有效时间 > 0,这个 cookie 一定会存储到硬盘文件当中
      • 设置 cookie 的有效时间 = 0 呢?
        • 表示该 cookie 被删除,主要应用在:使用这种方式删除浏览器客户端上的同名 cookie。
      • 设置 cookie 的有效时间 < 0 呢?
        • 保存在浏览器运行内存中,和不设置时一样。
    • cookie 有啥用呢?

      • cookie 和 session 机制其实都是为了保存会话的状态

      • cookie 是将会话的状态保存在浏览器客户端上( cookie 数据是存储在浏览器客户端上的)

        session 是将会话的状态保存在服务器端上( session 对象是存储在服务器上的)

      • 为什么要有 cookie 和 session 机制呢?

        • 因为 HTTP 协议是无状态无连接协议。
    • 浏览器什么时候会发送 cookie,发送哪些 cookie 给服务器?

      在 HTTP 协议中是这样规定的:当浏览器发送请求的时候,会自动携带该 path 下的 cookie 数据给服务器(URL)

      关于 cookie 的 path,cookie 关联的路径:

      • 假设现在在服务端生成 cookie,发送给浏览器的是请求路径为 “http://localhost:8080/servlet13/cookie/generate” 生成的 cookie(cookie 在服务端生成,发送给浏览器客户端),如果该 cookie 没有设置 path,默认的 path 是什么?

        • 默认的 path 是:http://localhost:8080/servlet13/cookie 以及它的子路径。

          也就是说,以后只要浏览器的请求路径是 http://localhost:8080/servlet13/cookie 这个路径以及这个路径下的子路径,该 cookie 都会被浏览器发送给服务器。

        • 默认情况下,**如果不设置 Cookie 的 path,默认是 “/项目名/当前路径的上一层地址”**,如:在请求路径:/cookie/cookieDome/servlet/login 下,服务端生成的 cookie 发送给了浏览器;则后面 Cookie 会被浏览器发送给服务端的请求路径为 /cookie/cookieDome/servlet 及这个路径下的子路径。

          ![](../../../../../Running Noob/计算机/Typora笔记/笔记-git仓库/JavaWeb-notebook/session+cookie/cookie路径.png)

      • 手动设置 cookie 的 path

        • cookie.setPath(“/servlet13”); 表示只要是这个 servlet13 项目的请求路径,都会提交这个 cookie 给服务器。
  • cookie 的经典案例:

    • 京东商城,在未登录的情况下,向购物车中放几件商品。然后关闭商城,再次打开浏览器,访问京东商城的时候,购物车中的商品还在,这是怎么做的?我没有登录,为什么购物车中还有商品呢?
      • 将购物车中的商品编号放到 cookie 当中,cookie 保存在硬盘文件当中。这样即使关闭浏览器。硬盘上的 cookie 还在。下一次再打开京东商城,查看购物车的时候,会自动读取本地硬盘中存储的 cookie,拿到商品编号,动态展示购物车中的商品。
        • 京东存储购物车中商品的 cookie 可能是这样的:productIds=xxxxx,yyyy,zzz,kkkk
        • 注意:cookie 如果清除掉,购物车中的商品就消失了。
    • 126 邮箱中有一个功能:十天内免登录
      • 这个功能也是需要 cookie 来实现的。
      • 怎么实现的呢?
        • 用户输入正确的用户名和密码,并且同时选择十天内免登录。登录成功后。浏览器客户端会保存一个 cookie,这个 cookie 中保存了用户名和密码等信息,这个 cookie 是保存在硬盘文件当中的,十天有效。在十天内用户再次访问 126 的时候,浏览器自动提交 126 的关联的 cookie 给服务器,服务器接收到 cookie 之后,获取用户名和密码,验证,通过之后,自动登录成功。
        • 怎么让 cookie 失效?
          • 十天过后自动失效。
          • 或者改密码。
          • 或者在客户端浏览器上清除 cookie。

在Java中使用cookie

  • cookie 机制和 session 机制其实都不属于 java 中的机制,实际上 cookie 机制和 session 机制都是 HTTP 协议的一部分

    php 开发中也有 cookie 和 session 机制,只要是你是做 web 开发,不管是什么编程语言,cookie 和 session 机制都是需要的

    • HTTP 协议中规定:任何一个 cookie 都是由 name 和 value 组成的。name 和 value 都是字符串类型

      在 HTTP 协议中是这样规定的:当浏览器发送请求的时候,会自动携带该 path 下的 cookie 数据给服务器(URL)。

  • 在 java 的 servlet 中,对 cookie 提供了哪些支持呢?

    • 提供了一个 Cookie 类来专门表示 cookie 数据。jakarta.servlet.http.Cookie;
    • java 程序怎么把 cookie 数据发送给浏览器呢?response.addCookie(cookie);
  • 浏览器发送 cookie 给服务器了,服务器中的 java 程序怎么接收?

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
    throws ServletException, IOException {
    Cookie[] cookies = request.getCookies(); // 这个方法可能返回null,没有提交cookie的时候
    if (cookies != null) {
    for (Cookie cookie : cookies) {
    // 获取cookie的name
    String name = cookie.getName();
    // 获取cookie的value
    String value = cookie.getValue();
    System.out.println(name + " = " + value);
    }
    }
    }
  • Java 中 Cookie 对象的常用相关方法小结:

    • cookie.setMaxAge(60 * 60); 设置 cookie 在一小时之后失效。
    • cookie.setPath(“/servlet13”); 手动设置 cookie 的路径。
    • response.addCookie(cookie); java 程序把 cookie 数据发送给浏览器。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
    throws ServletException, IOException {
    // 创建cookie对象
    Cookie cookie1 = new Cookie("productId", "A123");
    Cookie cookie2 = new Cookie("name", "zhangsan");

    // 设置cookie在一小时之后失效(保存在硬盘文件中)
    //cookie.setMaxAge(60 * 60);
    // 设置cookie的有效期为0,表示该cookie被删除,主要应用在:使用这种方式删除浏览器客户端上的同名cookie
    //cookie.setMaxAge(0);
    // 设置cookie的有效期 < 0,表示该cookie不会被存储在硬盘,只是保存在浏览器运行内存中
    //cookie.setMaxAge(-1);

    // 默认情况下,没有设置path的时候,cookie关联的路径是什么,是 `“/项目名/当前路径的上一层地址”
    // 设置cookie的路径
    cookie1.setPath(request.getContextPath()); //表示只要是在该应用下,都发送这个cookie给服务端
    cookie2.setPath(request.getContextPath());

    // 将cookie响应到浏览器
    response.addCookie(cookie1);
    response.addCookie(cookie2);
    }
    • Cookie[] cookies = request.getCookies(); 获取浏览器客户端发送给服务端的 cookie 数据。
    • String name = cookie.getName(); 获取 cookie 的 name。
    • String value = cookie.getValue(); 获取 cookie 的 value。
---------------The End---------------