JavaEE进阶(2) Spring Web MVC: Session 和 Cookie

在 Web 开发中,CookieSession 是两种常见的会话管理技术。它们的主要区别在于存储位置和管理方式。

  • Cookie 是存储在客户端(浏览器)的一小段文本信息。
  • 由服务器发送并存储在客户端,每次请求时浏览器都会将相关的 Cookie 附带在请求头中。
  • Cookie 适用于存储用户偏好设置、登录信息(通常结合加密)等。
  • Cookie 具有生命周期(如 Session Cookie、持久 Cookie)。
  • 由于 Cookie 存储在客户端,可能存在安全隐患,例如被篡改、伪造。

Session

  • Session 存储在服务器端,一般使用 Session ID 来标识客户端。
  • 服务器在创建 Session 时会生成一个唯一的 Session ID,并通过 Cookie 或 URL 传递给客户端。
  • 适用于存储登录状态、购物车信息等需要保密的数据。
  • Session 依赖于服务器的资源,过多的 Session 可能会影响服务器性能。

Spring MVC 提供了多种方式来获取和设置 Cookie、Session,以下是常见的使用方式。

2.1 代码示例

java 复制代码
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.*;

@RestController
@RequestMapping("/header")
public class HeaderController {
    
    // 获取 Cookie
    @RequestMapping("/getCookie")
    public String getCookie(HttpServletRequest request){
        Cookie[] cookies = request.getCookies();
        if (cookies != null) {
            for (Cookie cookie: cookies) {
                System.out.println(cookie.getName() + ": " + cookie.getValue());
            }
        }
        return "获取 Cookie 成功";
    }

    // 通过 @CookieValue 获取 Cookie
    @RequestMapping("/getCookie2")
    public String getCookie2(@CookieValue("bite") String bite){
        return "从 Cookie 中获取信息: bite = " + bite;
    }

    // 设置 Session
    @RequestMapping("/setSession")
    public String setSession(HttpServletRequest request){
        HttpSession session = request.getSession();
        session.setAttribute("userName", "zhangsan");
        session.setAttribute("age", 15);
        return "设置 Session 成功";
    }

    // 获取 Session(方式 1)
    @RequestMapping("/getSession")
    public String getSession(HttpServletRequest request){
        HttpSession session = request.getSession();
        String userName = (String) session.getAttribute("userName");
        System.out.println(session.getAttribute("age"));
        return "从 Session 中获取信息: userName = " + userName;
    }

    // 获取 Session(方式 2)
    @RequestMapping("/getSession2")
    public String getSession2(HttpSession session){
        String userName = (String) session.getAttribute("userName");
        System.out.println(session.getAttribute("age"));
        return "从 Session2 中获取信息: userName = " + userName;
    }
    
    // 通过 @SessionAttribute 获取 Session
    @RequestMapping("/getSession3")
    public String getSession3(@SessionAttribute("userName") String userName){
        return "从 Session3 中获取信息: userName = " + userName;
    }

    // 获取请求头中的 User-Agent
    @RequestMapping("/getHeader")
    public String getHeader(HttpServletRequest request){
        String userAgent = request.getHeader("User-Agent");
        return "User-Agent: " + userAgent;
    }
    
    // 通过 @RequestHeader 获取 User-Agent
    @RequestMapping("/getHeader2")
    public String getHeader2(@RequestHeader("User-Agent") String userAgent){
        return "User-Agent: " + userAgent;
    }
}

3. 高频面试题解析

对比项 Cookie Session
存储位置 客户端(浏览器) 服务器
生命周期 受浏览器控制,过期后自动删除 受服务器控制,超时后销毁
适用场景 轻量级信息,如用户偏好设置 需要保护的信息,如登录状态
安全性 容易被篡改,需加密 更安全,存储在服务器端
依赖性 依赖客户端 依赖服务器

2. 如何防止 Session 被劫持?

  • 使用 HTTPS 进行加密传输,防止中间人攻击。
  • 使用 HttpOnly Cookie,防止 JavaScript 访问。
  • 绑定 SessionID 与客户端信息,如 IP、User-Agent。
  • 及时销毁 Session,如用户退出登录后调用 session.invalidate()

SessionID 是 Session 机制的唯一标识符,为了让服务器识别每个客户端的 Session,通常将其存储在 Cookie 中。

4. 如何在 Spring Boot 中自定义 Session 过期时间?

可以在 application.properties 中配置:

复制代码
server.servlet.session.timeout=30m # 30 分钟过期

5. 如何让 Session 在多个服务器之间共享?

  • 使用 Redis 存储 Session(Spring Session + Redis)。
  • 通过 数据库 共享 Session。
  • 采用 Sticky Session 方式,将相同客户端的请求始终转发到同一台服务器。

4. 总结

  • Cookie 适用于存储简单的客户端信息,如用户 ID、偏好设置。
  • Session 适用于存储需要保密的数据,如登录信息。
  • Spring Web MVC 提供了 @CookieValue 和 @SessionAttribute 等注解,让我们更方便地操作 Cookie 和 Session。
  • Session 安全性需要特别注意,如使用 HTTPS、HttpOnly、Session 绑定客户端等方式防止劫持。
  • 面试中需要理解 Cookie 和 Session 的原理及其适用场景,同时掌握 Spring Web MVC 提供的相关功能。

通过本文的学习,你应该对 Spring MVC 的 Session 和 Cookie 处理有了更深入的理解,并能在实际开发和面试中灵活应用!

相关推荐
ℋᙚᵐⁱᒻᵉ鲸落2 小时前
移动端滑动手势冲突:overflow: auto导致外层横向滑动失效
前端·javascript·css·vue.js·html
学长毕业设计2 小时前
基于SpringBoot的公益基金管理系统(源码+文档+讲解视频)
java·spring boot·后端
东小西2 小时前
【SAA实战】第 3 篇 · 工具调用全攻略:把业务能力交给 Agent 自己调度
java·后端·spring
东小西3 小时前
【SAA实战】第 4 篇 · Agent 短期记忆:saver 让 Agent 跨轮记得住(threadId 隔离)
java·后端·spring
许彰午3 小时前
22-DataCenter报文序列化
java·低代码·架构·状态模式
2601_962065253 小时前
[MySQL] SQL优化之性能分析
java·sql·mysql
默_笙3 小时前
🎃 前端学了 Next.js,后端该学啥?NestJS 就是 Node 版的蜜雪冰城
前端·javascript
小范同学_3 小时前
JDK1.7 与 JDK1.8 HashMap 底层原理对比 + 数组并发扩容死循环详解
java·开发语言
weixin_416667964 小时前
【无标题】
运维·服务器·网络
予昊4 小时前
从零实现“在线五子棋对战“:WebSocket 实时通信 + 段位匹配
java·开发语言·网络·websocket