JavaWeb~Servlet~深入理解Cookie

什么是Cookie

HTTP协议本身是无状态的,这里的无状态指的是客户端和服务器之间不需要建立起持久的连接。即客户端向服务器发起了一个请求,服务器返回响应,返回响应后,这个连接就被关闭了,不保留任何和这次连接的有关信息。也就是说,HTTP请求只能由客户端向服务器发起,而服务器不能向客户端发送数据。即服务器不能辨识出请求的身份信息。

Cookie实际上是一小段的文本信息,是一串字符串,按照键值对(key-value)的格式组织起来。
当客户端向服务器发送请求后,如果服务器需要记录该请求的身份信息,或者记录用户状态,就会给对应的请求颁发一个Cookie,当下次浏览器再访问这个网站的时候,就会将请求的网址和Cookie一同发送给服务器,服务器检查该Cookie,就可以确认用户状态了。

这就类似于银行卡,当我们第一次去银行办理业务的时候,银行会给你一张银行卡,卡里保存了你的身份信息,电话号码,密码等等信息,当你下次再去银行的时候,直接出示银行卡就可以办理相关业务了。
也像是去医院看病时的就诊卡,第一次去看病,需要办理就诊卡,卡里保存了你的身份信息,余额等等,去具体的科室做检查,拿药时,直接出示就诊卡就可以知道你的身份信息。

Cookie工作原理

cookie是本地浏览器提供的功能,可以将一些数据储存起来。Cookie其实是储存在浏览器中的纯文本,浏览器的安装目录下会专门有一个cookie文件夹来存放各个域下设置的Cookie.
当网页要发送请求时,浏览器会先检查是否有响应的Cookie,有则自动添加在request header(请求头)的cookie字段中,这个过程是浏览器自动帮我们完成的。每一次请求浏览器都会进行一次这样的操作。

当我们第一次访问并登录一个网站的时候,Cookie的设置会经历以下几个步骤:

  • 客户端发送请求到服务器
  • 服务器返回响应+Set-Cookie字段
  • 客户端保存Cookie
  • 客户端再向服务器发送请求时,会自动将Cookie添加到请求头中
  • 服务器辨识出请求身份信息,直接发送数据。
    在这里插入图片描述
    我们用代码简单验证,在doGet方法中创建新的Cookie,访问抓包观察。
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@WebServlet("/testCookie")
public class TestCookie extends HttpServlet {
    
    
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    
    
        Cookie cookie=new Cookie("mcrwayfun",System.currentTimeMillis()+"");
        //设置生命周期为MAX_VALUE
        cookie.setMaxAge(Integer.MAX_VALUE);
        resp.addCookie(cookie);
    }
}

抓包查看请求内容,可以看到请求中有Cookie,返回的响应中有Set-Cookie.
在这里插入图片描述
在这里插入图片描述

Cookie属性

Cookie本身自带一些属性,比如这个Cookie什么时候失效,要发送到哪个域名、哪个路径等等.当我们设置任何一个Cookie的时候,都可以设置这些相关的属性,如果不设置,就会使用这些属性的默认值。设置时,属性与属性之间通过 一个分号和一个空格隔开。

属性项 属性项介绍
NAME=VALUE 键值对,可以设置要保存的Key/Value,注意这个名字不能和其他的属性名称相同
Expires 设置Cookie的有效期
Domain 设置域名,如domain=“www.sogou.com”
Path 设置的Cookie的路径 ,如path=/wp-admin/
Secure 设置安全性,设置了该属性,只有在SSH连接时才会传送Cookie

格式举例:

"key=name; expires=Thu, 25 Feb 2016 04:18:00 GMT; domain=ppsc.sankuai.com; path=/; secure; HttpOnly"

下面详细介绍这些属性:
expires
expires选项用来设置cookie的有效日期。设置时,必须将expires设置成GMT格式的时间。
设置GMT时间可以通过 new Date().toGMTString()方法或者 new Date().toUTCString() 方法来获得

如expires=Thu,25 Feb 2020 04:18:00 GMT表示cookie会在2020年2月25日4.18分后失效,对于失效的Cookie,会被浏览器自动清除。如果没有设置该选项,就会默认有效期是session,即会话Cookie,这总Cookie在浏览器关闭后就没有了。

expires是http/1.0协议中的选项,在新的http/1.1协议中已经由max-age选项代替,两者的作用都是限制cookie的有效时间。

maxAge表示Cookie的有效期时,单位时秒。Cookie中提供了两个方法来操作该属性,一个是getMaxAge()和setMaxAge(int maxAge)来读写该属性。

max-age的值有三种,分别是正数、负数和0

当maxAge的值为正数,就表示该Cookie会在maxAge秒之后自动失效。浏览器会将maxAge为正数的Cookie持久化,即写到本地的Cookie文件夹中,一旦写入,无论是用户关闭电脑还是浏览器,只要时间还在maxAge秒之前,登录网站时该Cookie就仍然有效。

像下面代码中的Cookie就永久有效。

   Cookie cookie=new Cookie("mcrwayfun",System.currentTimeMillis()+"");
        //设置生命周期为MAX_VALUE
        cookie.setMaxAge(Integer.MAX_VALUE);
        resp.addCookie(cookie);

当maxAge的值为负数的时候,就表示该Cookie只是一个临时的Cookie,不会被持久化,只是在当前窗口或者子窗口中有效,一旦关闭浏览器,Cookie会立即失效。

        Cookie cookie = new Cookie("mcrwayfun",System.currentTimeMillis()+"");
        // MaxAge为负数,是一个临时Cookie,不会持久化
        cookie.setMaxAge(-1);
        resp.addCookie(cookie);

当maxAge为0时,表示立即删除Cookie

        Cookie[] cookies = req.getCookies();
        Cookie cookie = null;

        // get Cookie
        for (Cookie ck : cookies) {
    
    

            if ("mcrwayfun".equals(ck.getName())) {
    
    
                cookie = ck;
                break;
            }
        }

        if (null != cookie) {
    
    
            // 删除一个cookie
            cookie.setMaxAge(0);
            resp.addCookie(cookie);
        }

domain和path
domain是域名,path是路径,两者相加就是URL,domina和path限制了cookie能被那些URL访问。

假设我们将Cookie的domain属性设置为sogou.com,若请求的URL的域名是“sogou.com”或者其子域如“api.baidu.com”、“dev.api.baidu.com”,且 URL 的路径是“/ ”或子路径“/home”、“/home/login”,则浏览器会将此 cookie 添加到该请求的 cookie 头部中。

如果没有设置这两个属性,就会使用默认值。domain的默认值会被设置为该Cookie的网页所在的域名。而path的默认值会被设置为cookie网页所在的目录。

secure
secure属性用来确保Cookie只会在安全的请求中发送,一般情况下,这个属性默认是空,不论是HTTP还是HTTPS协议Cookie都会被添加到请求头中,如果设置了该属性,那么只有在是SSH安全连接时才会将Cookie添加到请求中。

我们该如何使用Cookie

修改和删除Cookie

HttpServletResponse提供的Cookie操作只有一个添加操作:addCookie(Cookie cookie).
所以如果想要修改Cookie只能使用一个同名的Cookie覆盖原来的Cookie.
如果想要删除Cookie,只需要创建一个新的同名Cookie,并将其有效期maxAge设为0,覆盖原来的Cookie即可。

注意,新的Cookie,除了value、maxAge之外,其他的属性比如name、path、domain都必须与原来的一致才能达到修改或者删除的效果,否则浏览器会认为是两个Cookie,不予覆盖。

设置Cookie

Cookie可以有客户端来设置,也可以由服务器端来设置。

服务器端设置

不论是客户端请求一个资源文件,还是发送一个ajax请求,服务器都会返回response.
在响应头中的set-cookie就是专门用来设置Cookie的.
如下图,response header中有5个set-cookie字段,那每一个字段就会对应设置一个Cookie.而set-cookie的值就是普通的字符串。
在这里插入图片描述
一个set-Cookie字段只能设置一个Cookie,如果想要设置多个Cookie,就需要添加多个set-Cookie字段。且在该字段中,可以设置Cookie的所有属性。

客户端设置

在客户端中我们可以通过JavaScript代码来进行设置。

如下代码:

document.cookie = "name=Jonh; ";

在控制台中我们可以看到该Cookie成功设置,并且domain、path、expires都用了默认值。
在这里插入图片描述

如果想要设置多个Cookie,代码如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>

<script>

  //设置了5个Cookie
    document.cookie = "name=Jonhs; ";
    document.cookie = "name=Jonh; age=12; class=111";
    document.cookie = "name=Jonh";
    document.cookie = "age=12";
    document.cookie = "class=111";
</script>
</body>
</html>

设置成功。
在这里插入图片描述

什么样的数据适合放在Cookie中

存储在Cookie中的数据,每次都会被浏览器自动放在http请求中,如果这些数据不是每次请求都需要发送给服务器的,那浏览器的这种自动处理无疑是增加了开销,但如果这些数据是每次请求都需要发送给服务器的,那浏览器的这种自动处理就帮助我们省去了大量的重复添加操作。
所以每次请求都需要的数据就适合放在Cookie中,比如典型的身份认证信息,这也是Cookie被常用于实现网页登录功能。

每个域名下的Cookie大小最大为4KB,每个域名下的cookie数量最多为20个(也有的浏览器支持的数量大于20个)

Cookie格式

Cookie本身是储存在浏览器中的字符串,并且格式类似于键值对,由key=value 构成,键值对之间由一个 分号 和一个空格隔开。

参考文章:
https://blog.csdn.net/playboyanta123/article/details/79464684
https://www.jianshu.com/p/6fc9cea6daa2

猜你喜欢

转载自blog.csdn.net/Merciful_Lion/article/details/123601379