Session&Cookie- 会话跟踪技术详解

Session & Cookie 会话跟踪技术

Cookie&Session出现的原因:HTTP协议的问题所在----HTTP无状态

HTTP协议是无状态的,也就是没有记忆力,-----一个会话中的多个请求之间无法直接共享数据

通过作用域去共享的数据是作用域中的数据,不是请求之间的数据

解决方法
  1. 传递参数的方式
    • 直接在路径上带参数(麻烦且数据不安全, 不推荐)

      <%@ page contentType="text/html;charset=UTF-8" language="java" %>
      <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
      <html>
      <head>
      	<title>邮件列表</title>
      </head>
      <body>
      	欢迎:${username} <br/>
      	<c:forEach items="${list}" var="email">
      		<a href="/http/content">${email}</a> <br/>
      	</c:forEach>
      </body>
      </html>
      
      package cn.wolfcode.web._01_http;
      
      @WebServlet("/http/content")
      public class ContentServlet extends HttpServlet {
          @Override
          protected void service(HttpServletRequest req, HttpServletResponse resp)throws ServletException, IOException {
              // 处理请求编码
              req.setCharacterEncoding("UTF-8");
              // 接受请求参数
              String username = req.getParameter("username");
              req.setAttribute("username", username);
              // 模拟从数据库中查询到邮件内容,放到 request 作用域中
              req.setAttribute("content", "这是邮件内容");
              req.getRequestDispatcher("/WEB-INF/views/content.jsp").forward(req,resp);
      	}
      }
      
    问题:一次会话中多次请求,不共享数据,导致用户显示不出来。但若通过路径携带的方式解决该问题,会把用户信息暴露在路径上,不安全
  2. 会话跟踪技术

    cookie和session

Cookie
概述: cookie是客户端技术

程序把每个用户的数据以 cookie 的形式写给用户各自的浏览器。当用户使用浏览器再去访问服务器中的 Web 资源时,就会带着各自的数据到服务器。这样,Web 资源处理的就是用户各自的数据了

思考:
问题答案
Cookie 是服务器端创建的还是客户创建的?服务器端程序创建
Cookie 从哪里带到哪里?服务器端 -> 客户端
Cookie 最终存在什么地方浏览器
Cookie 什么时候实现数据共享再一次访问服务器端资源时
Cookie 中数据的传递方向?浏览器 -> 服务器(Cookie)-> 浏览器(存入)-> 服务器(获取Cookie数据)
Cookie原理?

当用户第一次发送数据到服务器时由服务器创建Cookie对象(封装用户数据),把Cookie响应给浏览器,当二次访问时用户不需要重新填写用户数据,由浏览器发送对应Cookie给服务器,服务器获取Cookie中的数据

Cookie 基本使用
  1. 创建Cookie对象

    Cookie cookie = new Cookie (String name, String value);

    属性方法描述
    namegetName()共享数据(唯一)
    valuegetValue()获取要共享的数据
  2. 响应Cookie对象给浏览器

    使用响应对象中的addCookie(Cookie对象) 将数据响应给浏览器

    response.addCookie(cookie);

  3. 服务端获取浏览器发送的Cookie

    浏览器发送请求时,自动将Cookie发送到服务器,服务器程序直接获取即可

    数据在请求中可以使用请求对象中的getCookies()方法获取所有的Cookie对象

    Cookie[] cookies = request对象.getCookies();

  4. 响应对应数据给浏览器
    1. Java代码:
    //创建Cookie对象,存入数据响应给浏览器
    @WebServlet("/cookie/login")
    public class LoginServlet extends HttpServlet {
        @Override
        protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            req.setCharacterEncoding("UTF-8");
            //接收请求参数
            String username = req.getParameter("username");
            String password = req.getParameter("password");
    
            if ("admin".equals(username) && "123456".equals(password)) {
                //将账号共享给index.jsp页面
                req.setAttribute("username",username);
                //创建cookie对象同时设置了共享数据
                //Cookie的默认路径是它所在Servlet的相对路径
                Cookie cookie = new Cookie("username", username);
                //修改cookie的路径
                cookie.setPath("/");
                //将cookie中的数据响应到浏览器中
                resp.addCookie(cookie);
    
                //账号密码正确,跳转到邮箱首页
                req.getRequestDispatcher("/WEB-INF/views/cookie/index.jsp").forward(req,resp);
            }
        }
    }
    
    //在Servlet中获取Cookie数据
    @WebServlet("/cookie/list")
    public class ListServlet extends HttpServlet {
        @Override
        protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            req.setCharacterEncoding("UTF-8");
            //从cookie中接收共享数据
            Cookie[] cookies = req.getCookies();
            for (Cookie cookie : cookies) {
                if ("username".equals(cookie.getName())) {
                    //System.out.println(cookie.getValue());
                    //req.setAttribute("username",cookie.getValue());
                    //break;
                    //修改cookie
                    //cookie.setValue("hhhh");
                    //将修改后的cookie重新响应给浏览器
                    //设置当前cookie存活的时间---默认是一个会话cookie
                    cookie.setMaxAge(60*60*30*24);
                    //resp.addCookie(cookie);
                }
            }
            req.getRequestDispatcher("/WEB-INF/views/cookie/list.jsp").forward(req,resp);
        }
    }
    
    @WebServlet("/cookie/content")
    public class ContentServlet extends HttpServlet {
        @Override
        protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            req.setCharacterEncoding("UTF-8");
            //从cookie中接收共享数据
            Cookie[] cookies = req.getCookies();
            for (Cookie cookie : cookies) {
                if ("username".equals(cookie.getName())) {
                    req.setAttribute("username",cookie.getValue());
                    break;
                }
            }
            req.getRequestDispatcher("/WEB-INF/views/cookie/content.jsp").forward(req,resp);
        }
    }
    
    1. 在JSP中获取Cookie数据----使用EL表达式

      <%--
          JSP获取cookie中的数据: ${cookie.cookie的名字.value}
          cookie: EL的内置对象,以Map结构封装了当前这一次请求所有的Cookie
              key是cookie的name
              value是cookie对象
          cookie.cookie名字: 对应的cookie对象
          cookie.cookie的名字.value: cookie的对象的属性名
      --%>
      <div align="left">欢迎[${cookie.username.value}]登录</div>
      <br>
      <a href="/cookie/content">邮件一</a>
      <br>
      <a href="/cookie/content">邮件二</a>
      <br>
      <a href="/cookie/content">邮件三</a>
      <br>
      <a href="/cookie/content">邮件四</a>
      </body>
      </html>
      
修改Cookie数据
  • 调用 Cookie 对象的 setValue 方法来覆盖原本的数据。
  • 重新创建一个同 name 的 Cookie 对象

注意:需要将修改之后的 Cookie 发送到浏览器中进行更新

resp.addCookie(修改后或者新的 Cookie 对象);
@WebServlet("/cookie/list")
public class ListServlet extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
	// 调用业务方法来处理请求,从数据库中查询邮件列表(模拟)
	List<String> list = Arrays.asList("邮件1", "邮件2", "邮件3");
    req.setAttribute("list", list);
    String username = null;
    Cookie[] cookies = req.getCookies();
    for(Cookie cookie : cookies) {
    	if("username".equals(cookie.getName())) {
    	// 方式一:修改 Cookie 中的数据
    	cookie.setValue("wolfcode1");
    	// 方式二:创建新的 Cookie 对象,设置名称为 username
    	// cookie = new Cookie("username", "wolfcode2");
    	// 记得使用 Response 对象响应回浏览器
    	resp.addCookie(cookie);
    	break;
    	}
    }
    req.getRequestDispatcher("/WEB-INF/views/list.jsp").forward(req, resp);
    }
}
设置Cookie存活时间
Cookie 对象的 setMaxAge(int expiry);
expiry数值例子含义
大于0setMaxAge(60)Cookie 存活的时间,单位为秒,例:60 秒
小于0setMaxAge(0)立即删除当前 Cookie 对象
等于0setMaxAge(-1)会话 Cookie,浏览器关闭则销毁
Cookie的分类

按客户端存储位置

  • 内存Cookie

    内存 Cookie 由浏览器维护,保存在内存中,浏览器关闭后就消失了,其存在时间是短暂的。硬盘Cookie 保存在硬盘里,有一个过期时间,除非用户手工清理或到了过期时间,硬盘 Cookie 不会被删除,其存在时间是长期的。所以,按存在时间,可分为

    • 非持久 Cookie
    • 持久 Cookie
  • 硬盘Cookie

默认情况下Cookie属于会话Cookie,即浏览器关闭则失效,无法使用

删除Cookie

删除 Cookie 只需要使用设置 Cookie 存活时间的方法即可,需要注意的是一般是中途删除

Cookie,不是创建了后马上删除,所以在设置删除之后需要重新发送给浏览器去更新删除

Cookie对象.setMaxAge(0);
resp.addCookie(Cookie 对象);
Cookie的域和路径作用

就是让浏览器能正确的区分每个Cookie是哪个请求需要的(先找域下所有的Cookie后找路径对应的Cookie发送给服务器)----安全

为了让浏览器可以识别 Cookie 发送给对应的服务器,以及识别哪些请求需要携带 Cookie,默认

Cookie 都带了服务器的识别标识以及需要带 Cookie 的资源标识,这是出于安全考虑,为了保护

Cookie 中的数据不被带到其他服务器中去

: 识别服务器,包括IP:端口或者域名:端口,可通过 Cookie 对象的 setDomain 方法设置;默认

Cookie 中的域是创建 Cookie 的服务器的域名,

分类:

  • 一级(主)域名:baidu.com
  • 多级域名:news.baidu.com

若想要在相同的主域名下来共享 Cookies 数据,例如,百度和百度地图,百度音乐共用账号,则只需要设置 Cookie 的 domain 即可。若主域不同,是无法共享 Cookie 数据

路径: 用于识别资源,通过Cookie对象的setPath方法设置------默认是创建Cookie的资源的路径

若想要在访问服务器上的任意资源都带上Cookie,则只需要在创建Cookie之后设置下path为/即可

cookie.setPath(“/”);

Cookie应用场景
  • 存用户标识,解决 HTTP 无状态问题
  • 登录时记住用户名
  • 未登录情况实现购物车
Cookie的问题
  • 若是一个用户一台电脑,没有问题,但是若多个人公用一个电脑就存在安全性问题
  • 一个 Cookie 只能设置一个值,值须字符串类型
  • 一台服务器在一个客户端存储的 Cookie 大小和数量有限
    • Cookie 大小限制在 4KB 之内
    • 一台服务器在一个客户端最多保存 20 个 Cookie
    • 一个浏览器最多可以保存 300 个 Cookie
Session
概述:Session是服务端技术

服务器在运行时可以为每一个用户的浏览器创建一个其独享的session对象,由于 session 为用户浏览器独享,所以用户在访问服务器的 Web 资源时,可以把各自的数据放在各自的 session 中,当用户再去访问服务器中的其它 Web 资源时,其它 Web 资源再从用户各自的 session 中取出数据为用户服务

思考
问题答案
Session 谁来创建服务器
Session存在什么地方服务器
Session什么时候实现数据共享再次访问服务器资源时
Session中数据的传输方向浏览器->服务器(Session)-------数据在服务器
服务器如何识别不同用户的Session浏览器->服务器(Session) sessionId
浏览器sessionId->服务器
Session的原理

Session 其底层依然需要依赖 Cookie 来传递 Session 的 id 值。存 sessionId 的 Cookie 为会话

Cookie

所以 Session 在浏览器关闭之后就无法使用了。原因是 sessionId 丢失了,服务器会在 30 分钟内清除无操作的 Session 对象

Session的基本使用
  1. 获取Session对象
    方法作用
    getSession(true)判断是否存在 Session,存在则获取,不存在则创建新 Session 对象返回
    getSession(false)判断是否存在 Session,存在则获取,不存在则返回 null (不符合需求)
    getSession()判断是否存在 Session(浏览器是否带了 sessionId),存在则获取,不存在则创建新 Session 对象返回(推荐)
  2. Session数据共享
    方法作用
    setAttribute(String name, Object value);设置属性名和属性值
    getAttribute(String name)通过属性名去获取属性值
    removeAttribute(String name)从 Session 中移除指定属性名的属性值(删除部分数据使用)
    invalidate()移除整个 Session 对象,删除所有的属性和属性值(删除全部数据使用)
  3. Session的超时管理------无操作的时间

    设置会话的有效时间

    1. 全局修改

      在web.xml中配置

    2. 局部修改

      // 设置 session 超时时间(单位秒)
      session.setMaxInactiveInterval(int interval);
      
  4. Session的使用规范

    Session的属性命名格式一般为: XXX_IN_SESSION(唯一的)

    session.setAttribute("USER_IN_SESSION",);
    

    Session可以存放多个数据,如果数据之间有联系的话可以将这部分数据封装成对象之后再存入Session中

    服务器在做 Session 数据共享时,Session 中的存储的对象类型须实现 java.io.Serializable 接口

  5. URL重写
    1. 为什么要重写URL

      Session是基于Cookie的,sessionId是存储在浏览器上的,用户可以选择不接受Cookie或者禁用Cookie,此时Session是无效的

    2. 解决方案: 在请求路径后面拼接jsessionid,使用 ; 间隔

      • 在Servlet中重写URL

        在请求的URL后拼接jsessionid--------response.encodeURL(“/session/list”)

        此时会自动检测用户是否接收Cookie,接收Cookie则不拼接,不接受Cookie则拼接 jsessionid

      • 在JSP中重写URL

        脚本重写(不使用)

        EL重写----效果同上

        • ${pageContext.response.encodeURL(“/session/list”)}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值