首页 云计算

Spring Boot Cookie & Session:打造有状态 HTTP 的“记忆”魔法

分类:云计算
字数: (6063)
阅读: (4260)
内容摘要:Spring Boot Cookie & Session:打造有状态 HTTP 的“记忆”魔法,

HTTP 协议本身是无状态的,这意味着服务器不会记住来自客户端的先前请求。但在实际应用中,我们需要服务器能够识别用户身份,并保持用户的会话状态,例如用户的登录状态、购物车信息等。本文将深入探讨在 Spring Boot 中如何利用 Cookie 和 Session 这两种技术来实现 无状态 HTTP 的“记忆”,并结合实际案例进行全栈实战。

Cookie:客户端的“小纸条”

Cookie 的原理

Cookie 是一种存储在用户浏览器上的小型文本文件,由服务器发送给客户端,客户端在后续的请求中会自动携带 Cookie。服务器通过读取 Cookie 中的信息来识别用户身份或者跟踪用户的行为。

Spring Boot 中 Cookie 的使用

在 Spring Boot 中,我们可以通过 HttpServletResponseHttpServletRequest 对象来操作 Cookie。以下是一个简单的例子:

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class CookieController {

    @GetMapping("/setCookie")
    public String setCookie(HttpServletResponse response) {
        // 创建 Cookie
        Cookie cookie = new Cookie("username", "axiaoyu"); // Cookie 名称和值
        cookie.setMaxAge(7 * 24 * 60 * 60); // 设置 Cookie 的有效期,单位秒,这里设置为 7 天
        cookie.setPath("/"); // 设置 Cookie 的作用路径
        // 将 Cookie 添加到响应中
        response.addCookie(cookie);
        return "Cookie 已设置";
    }

    @GetMapping("/getCookie")
    public String getCookie(HttpServletRequest request) {
        Cookie[] cookies = request.getCookies();
        if (cookies != null) {
            for (Cookie cookie : cookies) {
                if (cookie.getName().equals("username")) {
                    return "Cookie 值:" + cookie.getValue();
                }
            }
        }
        return "未找到 username Cookie";
    }
}

Cookie 的安全问题

Cookie 存在一些安全问题,例如:

Spring Boot Cookie & Session:打造有状态 HTTP 的“记忆”魔法
  • Cookie 欺骗:用户可以修改本地的 Cookie 值,从而冒充其他用户。
  • Cookie 窃取:通过 XSS 攻击等方式,攻击者可以获取用户的 Cookie 信息。

为了提高 Cookie 的安全性,可以采取以下措施:

  • 设置 HttpOnly 属性:禁止 JavaScript 访问 Cookie,防止 XSS 攻击。
    cookie.setHttpOnly(true);
    
  • 设置 Secure 属性:只允许在 HTTPS 连接中传输 Cookie。
    cookie.setSecure(true);
    
  • 使用签名 Cookie:对 Cookie 的值进行签名,防止用户篡改 Cookie。

Session:服务器的“备忘录”

Session 的原理

Session 是一种服务器端的技术,用于存储用户的会话信息。当用户第一次访问服务器时,服务器会创建一个 Session 对象,并生成一个 Session ID,然后将 Session ID 通过 Cookie 发送给客户端。客户端在后续的请求中会携带 Session ID,服务器根据 Session ID 找到对应的 Session 对象,从而识别用户身份。

Spring Boot 中 Session 的使用

Spring Boot 默认支持 Session 功能。我们可以通过 HttpSession 对象来操作 Session。以下是一个简单的例子:

Spring Boot Cookie & Session:打造有状态 HTTP 的“记忆”魔法
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class SessionController {

    @GetMapping("/setSession")
    public String setSession(HttpServletRequest request) {
        HttpSession session = request.getSession(); // 获取 Session 对象,如果不存在则创建
        session.setAttribute("userId", 12345); // 设置 Session 属性
        return "Session 已设置";
    }

    @GetMapping("/getSession")
    public String getSession(HttpServletRequest request) {
        HttpSession session = request.getSession();
        Integer userId = (Integer) session.getAttribute("userId"); // 获取 Session 属性
        if (userId != null) {
            return "Session 中的 userId:" + userId;
        }
        return "Session 中未找到 userId";
    }

    @GetMapping("/invalidateSession")
    public String invalidateSession(HttpServletRequest request) {
        HttpSession session = request.getSession(false); // 获取 Session 对象,如果不存在则不创建
        if (session != null) {
            session.invalidate(); // 销毁 Session
            return "Session 已销毁";
        }
        return "Session 不存在";
    }
}

Session 的集群问题

在分布式系统中,Session 的管理是一个复杂的问题。如果将 Session 存储在单台服务器上,当用户访问其他服务器时,就无法获取到 Session 信息。为了解决这个问题,可以使用以下方案:

  • Session 复制:将 Session 复制到所有的服务器上。这种方案简单易用,但会占用大量的内存资源,并且存在数据同步的问题。
  • 集中式 Session 管理:将 Session 存储在一个独立的服务器上,例如 Redis 或 Memcached。所有的服务器都从该服务器上获取 Session 信息。这种方案可以有效地解决 Session 的共享问题,但需要额外的服务器来存储 Session 数据,并且存在单点故障的风险。
  • 基于 Cookie 的 Session:将 Session 信息存储在 Cookie 中。这种方案可以避免 Session 共享的问题,但 Cookie 的大小有限制,并且存在安全问题。

在实际应用中,我们通常会选择集中式 Session 管理方案,例如使用 Spring Session 来管理 Session。 Spring Session 提供了多种 Session 存储方案,例如 Redis、JDBC 等。使用 Spring Session,只需要简单的配置,就可以实现 Session 的共享。

Spring Session + Redis 实战

  1. 添加依赖

    Spring Boot Cookie & Session:打造有状态 HTTP 的“记忆”魔法
    <dependency>
        <groupId>org.springframework.session</groupId>
        <artifactId>spring-session-data-redis</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-redis</artifactId>
    </dependency>
    
  2. 配置 Redis 连接信息

    application.propertiesapplication.yml 中配置 Redis 连接信息:

    spring.redis.host=127.0.0.1
    spring.redis.port=6379
    # spring.redis.password=your_redis_password
    
  3. 开启 Spring Session

    Spring Boot Cookie & Session:打造有状态 HTTP 的“记忆”魔法

    在 Spring Boot 启动类上添加 @EnableRedisHttpSession 注解:

    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.session.data.redis.config.annotation.web.http.EnableRedisHttpSession;
    
    @SpringBootApplication
    @EnableRedisHttpSession // 开启 Spring Session
    public class DemoApplication {
        public static void main(String[] args) {
            SpringApplication.run(DemoApplication.class, args);
        }
    }
    

    配置完成后,Spring Boot 会自动将 Session 存储到 Redis 中。不同的服务器可以共享同一个 Session。

实战避坑经验总结

  • Cookie 的大小限制:Cookie 的大小有限制,通常为 4KB。不要在 Cookie 中存储过多的数据。
  • Session 的有效期:Session 的有效期可以通过 session.setMaxInactiveInterval() 方法来设置。Session 过期后,服务器会自动销毁 Session 对象。
  • Session 的并发问题:在并发环境下,多个线程可能会同时访问同一个 Session 对象。为了避免并发问题,可以使用同步机制,例如使用 synchronized 关键字或者使用锁。
  • 反向代理和 Cookie 的 Path 问题:使用 Nginx 等反向代理时,需要注意 Cookie 的 Path 配置,确保 Cookie 在整个域名下都有效。例如,如果你的应用部署在 /app 目录下,需要将 Cookie 的 Path 设置为 /app
  • Nginx 负载均衡和 Session 粘滞:在使用 Nginx 进行负载均衡时,需要配置 Session 粘滞(sticky session),确保同一个用户的请求被路由到同一台服务器上,避免 Session 丢失。可以使用 Nginx 的 ip_hashleast_conn 策略来实现 Session 粘滞,或者使用 Spring Session 统一管理 Session。

总之,理解 Cookie 和 Session 的原理,合理地使用它们,可以帮助我们构建更加健壮和安全的应用。在分布式环境中,选择合适的 Session 管理方案至关重要,Spring Session + Redis 是一个不错的选择。

Spring Boot Cookie & Session:打造有状态 HTTP 的“记忆”魔法

转载请注明出处: 代码一只喵

本文的链接地址: http://m.acea4.store/blog/516953.SHTML

本文最后 发布于2026-04-06 05:10:02,已经过了21天没有更新,若内容或图片 失效,请留言反馈

()
您可能对以下文章感兴趣
评论
  • 咸鱼翻身 5 天前
    Cookie 安全性问题确实需要重视,HttpOnly 和 Secure 属性一定要设置。
  • 老实人 6 天前
    讲的很透彻,尤其是 Spring Session + Redis 的部分,正好解决了我的 Session 共享问题。
  • i人日记 1 天前
    Nginx 反向代理和 Cookie Path 这个坑我踩过,配置不当会导致登录失效,感谢提醒!
  • 星河滚烫 7 小时前
    Nginx 反向代理和 Cookie Path 这个坑我踩过,配置不当会导致登录失效,感谢提醒!