Cookie和Session

1 Cookie

1.1 介绍

Cookie(HTTP Cookie)是一种小型的文本信息,由服务器发送到用户的浏览器,然后存储键值对在用户的计算机上。Cookie通常用于跟踪用户的会话信息、个性化设置、购物车内容等,以实现在不同HTTP请求之间维护状态信息。
客户端有了 Cookie 后, 每次请求都发送给服务器。每个 Cookie 的大小不能超过 4kb。

1.2 浏览器查看 Cookie

例如谷歌浏览器查看 Cookie,按F12 在 DevTools 中的Application 里查看Cookies:
在这里插入图片描述
Cookie各属性如下表所示:
在这里插入图片描述

Cookie为什么需要设置HttpOnly和Secure属性呢?
当设置了 HttpOnly 属性时, 通过脚本将无法获取到 Cookie 信息,主要用于防止 XSS 攻击。 而一旦设置了 Secure 属性时, 前后端之间只能在 HTTPS 协议通信情况下, 浏览器才能访问 Cookie,使用 HTTP 协议时浏览器无法取到 Cookie 信息, 同样是对 Cookie 信息的保护。

1.3 创建Cookie

在这里插入图片描述
示例代码:

@WebServlet("/create-cookie")
public class CookieServlet extends HttpServlet {

    @Override
    protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        response.setContentType("text/html; charset=UTF-8");
        Cookie c1 = new Cookie("key1", "kong");
        Cookie c2 = new Cookie("key2", "xing");

        response.addCookie(c1);
        response.addCookie(c2);
        response.getWriter().print("Cookie添加成功");
    }
}

在浏览器 DevTools 中的 Application 里查看Cookies:
在这里插入图片描述

1.4 服务器获取Cookie

在这里插入图片描述
正常人写法:

CookieUtils工具类:

public class CookieUtils {

    public static Cookie findCookie(String name , Cookie[] cookies){
        if (name == null || cookies == null || cookies.length == 0) {
            return null;
        }
        for (Cookie cookie : cookies) {
            if (name.equals(cookie.getName())) {
                return cookie;}
        }
        return null;
    }
}

Servlet:

@WebServlet("/CookieServlet1")
public class CookieServlet1 extends HttpServlet {

    @Override
    protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        getCookie(request,response);
    }

    protected void getCookie(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        response.setContentType("text/html; charset=UTF-8");
        Cookie[] cookies = request.getCookies();
        for (Cookie cookie : cookies) {
            // getName 方法返回 Cookie 的 key(名)
            // getValue 方法返回 Cookie 的 value 值
            response.getWriter().write(cookie.getName() + "=" + cookie.getValue() + "<br/>");
        }
        Cookie iWantCookie = CookieUtils.findCookie("key1", cookies);

        if (iWantCookie != null) {
            response.getWriter().write("找到了需要的 Cookie");
        }
    }
}

JDK新特性写法:

@WebServlet("/getCookie")
public class CookieCreate extends HttpServlet {

    @Override
    protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        Optional<Cookie> c1 = getCookie("key1",request.getCookies());
        Optional<Cookie> c2 = getCookie("key2",request.getCookies());

        System.out.println(c1.get().getName() + " | " + c1.get().getValue());
        System.out.println(c2.get().getName() + " | " + c2.get().getValue());

        Cookie c3 = getCookie("key3", request.getCookies()).orElse(new Cookie("key3", "空"));
        System.out.println(c3.getName() + " | " + c3.getValue());
    }

    private Optional<Cookie> getCookie(String name ,Cookie[] cookies){
       return Arrays.stream(cookies).filter(c->name.equals(c.getName())).findFirst();
    }
}

1.5 Cookie 值的修改

方案一:

// 1、 先创建一个要修改的同名的 Cookie 对象
// 2、 在构造器, 同时赋于新的 Cookie 值。
Cookie cookie = new Cookie("key1","newValue1");
// 3、 调用 response.addCookie( Cookie ); 通知 客户端 保存修改
resp.addCookie(cookie);

方案二:

// 方案二:
// 1、 先查找到需要修改的 Cookie 对象
Cookie cookie = CookieUtils.findCookie("key2", req.getCookies());
if (cookie != null) {
// 2、 调用 setValue()方法赋于新的 Cookie 值。
cookie.setValue("newValue2");
// 3、 调用 response.addCookie()通知客户端保存修改
resp.addCookie(cookie);
}

1.6 Cookie 中的 expires 属性

Cookie 的生命控制指的是如何管理 Cookie,什么时候被销毁(删除)
setMaxAge()

  • 正数, 表示在指定的秒数后过期
  • 负数, 表示浏览器一关, Cookie 就会被删除(默认值是-1)
  • 零, 表示马上删除 Cookie
@Override
protected void service(HttpServletRequest request, HttpServletResponse response) throwsServletException, IOException {
	response.setContentType("text/html; charset=UTF-8");
	Cookie c1 = new Cookie("key1", "value1");
	Cookie c2 = new Cookie("key2", "value2");
	Cookie c3 = new Cookie("key3", "value3");
	c3.setMaxAge(60 * 60 * 24); //一天
	Cookie c4 = new Cookie("key4", "value4");
	c4.setMaxAge(-1);
	Cookie c5 = new Cookie("key5", "value5");
	c5.setMaxAge(0);
	
	response.addCookie(c1);
	response.addCookie(c2);
	response.addCookie(c3);
	response.addCookie(c4);
	response.addCookie(c5);
	response.getWriter().print("Cookie添加成功");
}

在浏览器 DevTools 中的 Application 里查看Cookies:
在这里插入图片描述

1.7 Cookie 中的 Domain 和 Path 属性

Cookie 的 Domain 默认值是 request.getServletName
Cookie 的 Path 默认值是 request.getContextPath

http://localhost:8080/cookie-demo/create-cookie  //产生cookie
http://127.0.0.1:8080/cookie-demo/create-cookie  //访问不到上面产生的cookie

得知Cookie不能跨域访问

实验一:
Cookie 的 Path 匹配规则是,前缀匹配

path = /;
path = /cookie-demo;
path = /cookie-demo/a.jsp;
以上的cookie访问/cookie-demo/a.jsp,会跟随请求一起访问;
path = /cookie/b.jsp的cookie访问/cookie-demo/a.jsp  不会跟随请求一起访问;

实验二:在不同的子域中,共享cookie
本地域名解析
在该路径下 C:\Windows\System32\drivers\etc\hosts 添加下列内容:

127.0.0.1 file.com
127.0.0.1 a.file.com
127.0.0.1 b.file.com
127.0.0.1 image.com

代码:

 	@Override
    protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		Cookie c10 = new Cookie("key10", "value10");
		c10.setDomain("file.com");
		Cookie c11 = new Cookie("key11", "value11");
		c11.setDomain("a.file.com");
		Cookie c12 = new Cookie("key12", "value12");
		c12.setDomain("b.file.com");
		Cookie c13 = new Cookie("key13", "value13");
		c13.setDomain("image.com");

		response.addCookie(c10);
        response.addCookie(c11);
        response.addCookie(c12);
        response.addCookie(c13);
	}

访问 http://a.file.com:8080/cookie-demo/create-cookie,产生cookie
访问 http://b.file.com:8080/cookie-demo/get-cookie,只有c10这个设置了顶级域的cookie可以被子域共享访问。

总结:cookie中只能设置当前域,和当前域的顶级域(比如a.file.com访问的,cookie可以设置为
a.file.com,file.com)

Cookie 的 path 属性可以有效的过滤哪些 Cookie 可以发送给服务器。 哪些不发。
path 属性是通过请求的地址来进行有效的过滤。

1.8 JS 中访问 Cookie

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="js/js.cookie.min.js"></script>
</head>
<body>
  <script>
      console.log(Cookies.get("key10"));

      Cookies.set('key21', 'value21', { expires: 7, path: '/cookie-demo' })

      Cookies.set('key22', 'value22', { expires: 7, path: '/cookie-demo', domain: ".file.com" })

      Cookies.set('key23', 'value23', { expires: 7, path: '/cookie-demo', domain: ".image.com" })
      
      console.log("-------------------")
      console.log(Cookies.get());
  </script>
</body>
</html>

先用 http://a.file.com:8080/cookie-demo/create-cookie 产生cookie
再用 http://a.file.com:8080/cookie-demo/c.html 获取cookie

在浏览器 DevTools 中的 Console 查看控制台打印:
在这里插入图片描述
在浏览器 DevTools 中的 Application 里查看Cookies:
在这里插入图片描述

2 Session

2.1 介绍

Session(会话)通常指的是Web应用程序中的用户会话,它是一种在服务器端维护的状态信息,用于跟踪用户与应用程序之间的交互。会话允许在用户在网站上浏览时保持用户的状态,以便存储和检索用户的数据,例如登录状态、购物车内容、用户首选项等。

以下是关于会话的一些重要概念和用法:

  1. 会话的创建:会话通常在用户访问Web应用程序时创建。当用户第一次访问网站时,服务器会为其创建一个唯一的会话标识符(Session ID),并将其存储在Cookie中或通过URL重写等方式传递给客户端。

  2. 数据存储和检索:在会话中,开发人员可以存储各种类型的数据,包括用户的登录信息、购物车内容、用户首选项等。这些数据存储在服务器端,与用户的会话相关联,并在会话期间保持不变。

  3. 会话生命周期:会话可以有不同的生命周期,通常分为以下几种:

    • 会话级别(Session-level):会话从用户首次访问Web应用程序开始,直到用户关闭浏览器或会话超时为止。
    • 请求级别(Request-level):会话仅在单个HTTP请求期间有效,不会被持久化。
    • 应用程序级别(Application-level):数据存储在整个Web应用程序的生命周期内,对所有用户共享。
  4. 会话超时:为了避免资源浪费,会话通常具有超时时间,即在一定时间内没有活动的会话会被销毁。超时时间可以在应用程序配置中进行设置。

  5. 会话管理:会话管理包括创建、销毁、存储和检索会话数据的操作。开发人员可以使用Web框架或Servlet容器提供的API来进行会话管理。常用的API包括HttpSession接口和与之相关的方法。

  6. 会话安全性:会话的安全性对于用户的隐私和数据保护至关重要。开发人员需要采取措施来防止会话劫持、会话固定等攻击,例如使用安全的会话标识符和HTTPS协议。

2.2 登录案例

login.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>登录</title>
</head>
<body>
    <form action="/session-demo/login" method="post">
        用户名:<input type="text" name="username"><br>
        密码:<input type="password" name="password"><br>
        <input type="submit">
    </form>
</body>
</html>

LoginServlet

@WebServlet("/login")
public class LoginServlet extends HttpServlet {

    @Override
    protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String username = request.getParameter("username");
        String password = request.getParameter("password");
        HttpSession session = request.getSession();

        if("kong".equals(username) && "123456".equals(password)){
            session.setAttribute("loginUser","kong");
            response.sendRedirect("/session-demo/getUser");
        }else {
            response.sendRedirect("/session-demo/login.html");
        }
    }
}

查看当前登录用户
GetUserServlet

@WebServlet("/getUser")
public class GetUserServlet extends HttpServlet {

    @Override
    protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        response.setContentType("text/html;charset=utf-8");
        PrintWriter out = response.getWriter();
        HttpSession session = request.getSession();
        String loginUser = session.getAttribute("loginUser").toString();
        out.println("用户:"+loginUser);
    }
}

2.3 cookie-session原理

第一次请求:
在这里插入图片描述
在浏览器 DevTools 中的 Application 里查看Cookies:
在这里插入图片描述

第二次请求服务器:
在这里插入图片描述
在这里插入图片描述

2.4 Session API操作

Session API 是用于在Java Web应用中管理会话(Session)的一组接口和类。通过Session,你可以在不同的HTTP请求之间存储和共享数据,以便在用户与应用程序之间保持状态信息。

以下是一些常用的Session操作,以及它们的示例代码:

  1. 获取Session对象

    HttpSession session = request.getSession();
    
  • true:默认,如果当前上下文有session使用当前session,如果没有产生新的session

  • false:得到当前上下文中的session,如果当前上下文没有session,不会主动产生session

    这将获取当前HTTP请求的Session对象,如果Session不存在,则创建一个新的Session。

  1. 向Session中存储数据

    session.setAttribute("username", "john_doe");
    

    这将在Session中存储一个名为 “username” 的属性,其值为 “john_doe”。

  2. 从Session中获取数据

    String username = (String) session.getAttribute("username");
    

    这将从Session中获取名为 “username” 的属性的值。

  3. 删除Session中的数据

    session.removeAttribute("username");
    

    这将从Session中删除名为 “username” 的属性。

  4. 设置Session的超时时间

    session.setMaxInactiveInterval(3600); // 设置Session的超时时间为1小时,单位为秒
    

    这将设置Session的最大不活动间隔时间为1小时,在用户一小时内没有活动时,Session将被销毁。

  5. 销毁Session

    session.invalidate();
    

    这将立即销毁Session,并清除其中的所有数据。

  6. 获取Session的ID

    String sessionId = session.getId();
    

    这将获取Session的唯一标识符(ID)。

Session 默认的超时时间长为 30 分钟。因为在 Tomcat 服务器的配置文件 web.xml中默认有以下的配置, 它就表示配置了当前 Tomcat 服务器下所有的 Session超时配置默认时长为: 30 分钟。

<session-config>
	<session-timeout>30</session-timeout>
</session-config>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值