Skip to content
not500
Go back

什么是Cookie?

On this page

什么是Cookie?

HTTP cookie(也称为 web cookie浏览器 cookie)是服务器存储在用户浏览器中的一小段信息。服务器在返回浏览器发出的请求的响应时设置 Cookie。浏览器存储 Cookie 并将其与后续请求一起发送回同一服务器。

Cookie有什么作用?

用户跟踪:

存储用户偏好:

跨请求识别客户端:

等等

在SpringBoot中创建Cookie

1、创建cookie

@RestController
@RequestMapping("/cookie")
public class CookieController {

    @GetMapping("/set")
    public String setCookie(HttpServletResponse response) {
        Cookie userNameCookie = new Cookie("username", "not500");
        userNameCookie.setPath("/");

        response.addCookie(userNameCookie);

        // 创建一个 cookie
        Cookie passwordCookie = new Cookie("password", "123456");
        //设置 cookie过期时间
        passwordCookie.setMaxAge(7 * 24 * 60 * 60); // expires in 7 days
        //添加到 response 中
        response.addCookie(passwordCookie);

        return "cookie is changed";
    }
}

2、发送请求

然后在浏览器中发送请求,可以在响应体中看到设置cookie的操作

浏览器网络面板中响应头的 Set-Cookie 字段

3、常见属性

cookie有几个常见的属性。name、value、domain、path、max-age、httponly、scure、sameSite

浏览器应用程序面板中查看 Cookie 属性
属性作用示例
name=value必填。Cookie的键值对lang=zh-CN
Domain指定Cookie适用的域名(含子域)Domain=.example.com
(适用于example.com及其子域)
Path指定Cookie生效的路径Path=/account
(只在/account及其子路径生效)
Expires绝对过期时间(GMT格式)Expires=Wed, 21 Oct 2025 07:28:00 GMT
Max-Age相对过期时间(单位:秒),比Expires
优先
Max-Age=3600
(1小时后过期)
Secure仅在HTTPS协议下发送Secure
HttpOnly禁止JS通过document.cookie
访问(防止XSS)
HttpOnly
SameSite跨站点请求时的Cookie发送策略(防CSRF)SameSite=Strict

name 和 value

cookie是以键值对的方式存储的,name也就是名称,value就是内容

domain 和 path

这两个属性可以控制cookie的访问范围

我们再发一次请求,可以看到在 请求体 中带了cookie

浏览器请求头中携带的 Cookie

但若将域名改成 127.0.0.1 ,就看不到刚刚设置的cookie了。 **不同域名下的 Cookie 默认不共享。**在该域名下发送之前的 /set,然后再 /get 就可以看到cookie 了。

127.0.0.1 域名下设置 Cookie 的请求

我们再看 path 属性,新建一个类,添加以下代码,然后在浏览器发送请求。

@RestController
@RequestMapping("/cookie2")
public class CookieController2 {

    @GetMapping("/get")
    public String readCookie(@CookieValue(value = "username", defaultValue = "null") String username
            ,@CookieValue(value = "password", defaultValue = "null") String password) {
        return "Hey! My username is " + username + "<br/>" + "My password is " + password;
    }
}

可以看到能读到 username,但是读不到 password,因为我们当前的路径是在 /cookie2下,username的有效路径是 /,password 的有效路径是 /cookie

/cookie2/get 只能读取 username Cookie

expires 和 max-age

我们之前设置的cookie中,password的过期时间是一个普通的时间,表示时间一到,该cookie就会被清楚,需要用户重新进行相关操作,例如登录。而username的过期时间是‘会话’,表面 一旦关闭浏览器,Cookie自动消失。

浏览器中显示持久 Cookie 和会话 Cookie 的过期时间

此外,因为 Servlet 规范遵循更现代的 HTTP/1.1 标准,采用 Max-Age 取代了 Expires,所以没有提供 setExpires() 方法。

Servlet Cookie API 中未提供 setExpires() 方法

secure + httpOnly + sameSite

secure

安全 Cookie 仅通过加密的 HTTPS 连接发送到服务器。安全 Cookie 无法通过未加密的 HTTP 连接传输到服务器。然后在浏览器发送之前的 /get 请求。

// 创建一个 cookie
Cookie secure = new Cookie("secure", "1");
//设置 cookie过期时间
secure.setMaxAge(7 * 24 * 60 * 60); // expires in 7 days
secure.setSecure(true);
//添加到 response 中
response.addCookie(secure);

但是却请求到了 scure 的cookie?

浏览器在localhost 或 127.0.0.1上,出于开发便利,部分浏览器放宽了Secure的限制

在 localhost 上 Secure Cookie 仍被发送

我们可以在 命令提示符(win + r,输入cmd)中使用 ipconfig 命令,查看自己的ip,然后在浏览器中 /get,就看不到了。在/get 前记得先 /set一下

在局域网 IP 地址下查看 Cookie,Secure Cookie 未被发送

httpOnly

Cookie 设置了 HttpOnly 属性,客户端脚本就无法访问该 Cookie。例如,不能使用 Document.cookie 属性访问 JavaScript 中的 HttpOnly Cookie。

sameSite

含义举例
Strict最严格,完全不允许跨站点发送(即便用户点击链接跳转也不会带Cookie)假如你现在在浏览一个博客网站,里面有一个github的链接,但github下的cookie设置了sameSite=Strict,那么你跳转过去后需要重新登录。
Lax默认。允许”导航行为”(比如点击链接)带上Cookie,但不允许跨站请求(如图片、iframe、Ajax、表单)设置为Lax,上面的案例中,就不需要重新登录了,但如果现在有按钮,点击按钮时向 github的开发api 发送ajax请求,那么cookie就带不过去了。
None允许完全的跨站请求,但必须与Secure一起使用(即HTTPS下)使用Https,且,任何请求都可以携带cookie

Lax下,各种请求发送Cookie的情况

请求类型示例正常情况Lax同源策略
链接<a href="..."></a>发送 Cookie发送 Cookie❌ 不受限制
预加载<link rel="prerender" href="..."/>发送 Cookie发送 Cookie❌ 不受限制
GET 表单<form method="GET" action="...">发送 Cookie发送 Cookie❌ 不受限制
POST 表单<form method="POST" action="...">发送 Cookie不发送❌ 不受限制
iframe<iframe src="..."></iframe>发送 Cookie不发送✅ 部分限制
AJAX$.get("...")发送 Cookie不发送✅ 完全限制
Image<img src="...">发送 Cookie不发送❌ 不受限制

CSRF

关于CSRF,可以阅读这篇文章——前端安全系列(二):如何防止CSRF攻击?


Share this post:

Next Post
Pi 的会话记忆机制