博主
258
258
258
258
专辑

第三十六节 SpringBoot开发中使用Cookie(一)

亮子 2023-09-26 02:59:32 6720 0 0 0

什么是cookie?

cookie就是一个小体积的键值对,格式:key=value;

什么要使用cookie?

客户端和服务器端,通常使用http协议来进行数据传输,而http协议是无状态的。也就是客户端向同一个服务器端发送的第一次Request和第二次Request,是没有关联的。

举个例子:小明第一次向服务器发起登陆请求,如果服务器不给小明返回cookie(本文不讨论token,session等其他方式验证用户登录态),小明第二次像服务器发送请求时,服务器是无法识别本次请求是小明发起的,小明就需要再次登陆。

因此需要cookie来保存一些用户信息,每次向相同的域名(domian)和路径(path)发送Request时都会携带cookie;

SpringBoot中如何使用cookie?

1、服务端如何获取cookie?

1)、通过HttpServletRequest对象,获取cookie

package com.shenma2009.cookie.controller;

import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Arrays;

/**
 * @author 军哥
 * @version 1.0
 * @description: IndexController
 * @date 2023/9/26 14:08
 */

@RestController
@Slf4j
@RequestMapping(value = "/index")
public class IndexController {

    @GetMapping(value = "/index")
    public String index(HttpServletRequest request, HttpServletResponse response) {
        Cookie[] cookies = request.getCookies();
        Arrays.stream(cookies).forEach(item -> {
            System.out.println(item.getName());
            System.out.println(item.getValue());
        });

        return "ok";
    }

}

2)、接口入参使用@CookieValue注解,获取cookie的值

package com.shenma2009.cookie.controller;

import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.CookieValue;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Arrays;

/**
 * @author 军哥
 * @version 1.0
 * @description: IndexController
 * @date 2023/9/26 14:08
 */

@RestController
@Slf4j
@RequestMapping(value = "/index")
public class IndexController {

    @GetMapping(value = "/hello")
    public String hello(@CookieValue(name = "cookieKey", required = false) String cookieKey) {
        System.out.println(cookieKey);
        return cookieKey;
    }
}

该注解由SpringWeb提供,主要有两个属性,默认Required为true,如果Request不包含该名字的cookie,则会报错。

2、服务端如何向客户端返回cookie?

创建一个cookie对象,通过HttpServletResponse返回给客户端。

Cookie类和HttpServletResponse以及HttpServletRequest类都在javax.servlet.http包下。

    @GetMapping(value = "/add")
    public String add(HttpServletResponse response) {
        Cookie cookie = new Cookie("cookieKey", "hello,world!");

        response.addCookie(cookie);

        return "add";
    }

3、Cookie类的属性

图片alt

  • Name和Value
    Name和Value是一个键值对。Name是Cookie的名称,Cookie一旦创建,名称便不可更改,一般名称不区分大小写;Value是该名称对应的Cookie的值,如果值为Unicode字符,需要为字符编码。如果值为二进制数据,则需要使用BASE64编码。

  • Domain
    Domain决定Cookie在哪个域是有效的,也就是决定在向该域发送请求时是否携带此Cookie,Domain的设置是对子域生效的,如Doamin设置为 .a.com,则b.a.com和c.a.com均可使用该Cookie,但如果设置为b.a.com,则c.a.com不可使用该Cookie。Domain参数必须以点(“.”)开始。

  • Path
    Path是Cookie的有效路径,和Domain类似,也对子路径生效,如Cookie1和Cookie2的Domain均为a.com,但Path不同,Cookie1的Path为 /b/,而Cookie的Path为 /b/c/,则在a.com/b页面时只可以访问Cookie1,在a.com/b/c页面时,可访问Cookie1和Cookie2。Path属性需要使用符号“/”结尾。

  • Expires/Max-age
    Expires和Max-age均为Cookie的有效期,Expires是该Cookie被删除时的时间戳,格式为GMT,若设置为以前的时间,则该Cookie立刻被删除,并且该时间戳是服务器时间,不是本地时间!若不设置则默认页面关闭时删除该Cookie。
    Max-age也是Cookie的有效期,但它的单位为秒,即多少秒之后失效,若Max-age设置为0,则立刻失效,设置为负数,则在页面关闭时失效。Max-age默认为 -1。

  • HttpOnly
    HttpOnly值为 true 或 false,若设置为true,则不允许通过脚本document.cookie去更改这个值,同样这个值在document.cookie中也不可见,但在发送请求时依旧会携带此Cookie。

  • Secure
    Secure为Cookie的安全属性,若设置为true,则浏览器只会在HTTPS和SSL等安全协议中传输此Cookie,不会在不安全的HTTP协议中传输此Cookie。

参考文档