什么是 Session?Web 开发中 Session 的使用与注意事项

什么是 Session?Web 开发中 Session 的使用与注意事项

✅ 引言

在 Web 开发中,HTTP 协议是无状态的,这意味着每次请求之间没有关联。为了实现用户登录、购物车、权限控制等功能,服务器需要一种机制来“记住”用户。Session(会话) 就是解决这一问题的核心技术之一。

本文将深入讲解:

  • 什么是 Session?
  • Session 的工作原理
  • 在 Java Web 和 Spring Boot 中如何使用 Session
  • 使用 Session 的最佳实践与常见注意事项
  • 安全风险与应对策略

并提供完整的 Java + Spring Boot 示例代码,帮助你全面掌握 Session 的使用。


📌 一、什么是 Session?

1.1 基本定义

Session(会话)是服务器端用于保存用户状态的一种机制。当用户访问服务器时,服务器为其创建一个唯一的会话(Session),并在内存或存储中保存该用户的相关信息(如登录状态、用户ID等)。

每个 Session 都有一个唯一的 Session ID,通常通过 Cookie 发送给客户端,后续请求中客户端携带该 ID,服务器据此识别用户。想象 Session 就像超市给你的会员卡,第一次访问时服务器给你生成一张唯一的 “会员卡”(Session ID),以后每次访问你都出示这张卡,服务器就能通过卡片识别你的身份和之前的操作记录。

1.2 工作流程图解

在这里插入图片描述

1.3 Session 的工作原理

Session的工作流程可以分为四个阶段:

  1. 创建阶段:当用户第一次访问服务器时,服务器会生成一个唯一的Session ID,并创建对应的Session对象存储用户数据。
  2. 传输阶段:服务器通过Set-Cookie响应头,将Session ID发送给客户端,客户端会将其保存在Cookie中。
  3. 验证阶段:后续请求中,客户端会自动在Cookie中携带Session ID,服务器通过这个ID找到对应的Session对象。
  4. 销毁阶段:当用户登出或会话超时后,服务器会删除Session对象,客户端Cookie也会被清除或标记为过期。

📌 二、Session 的使用场景

  • 用户登录状态保持
  • 购物车信息存储
  • 表单防重复提交
  • 一次性验证码(如短信验证码)
  • 权限控制与访问记录

📌 三、Java Web 中使用 Session(原生 Servlet)

3.1 获取或创建 Session

@WebServlet("/login")publicclassLoginServletextendsHttpServlet{@OverrideprotectedvoiddoPost(HttpServletRequest req,HttpServletResponse resp){String username = req.getParameter("username");// 获取或创建 SessionHttpSession session = req.getSession();// 存储用户信息 session.setAttribute("username", username); session.setAttribute("loginTime",newDate()); resp.getWriter().println("登录成功,欢迎 "+ username);}}

3.2 读取 Session 数据

@WebServlet("/profile")publicclassProfileServletextendsHttpServlet{@OverrideprotectedvoiddoGet(HttpServletRequest req,HttpServletResponse resp){HttpSession session = req.getSession(false);// 不自动创建if(session !=null&& session.getAttribute("username")!=null){String username =(String) session.getAttribute("username");Date loginTime =(Date) session.getAttribute("loginTime"); resp.getWriter().println("用户:"+ username +",登录时间:"+ loginTime);}else{ resp.setStatus(401); resp.getWriter().println("请先登录");}}}

3.3 注销 Session

@WebServlet("/logout")publicclassLogoutServletextendsHttpServlet{@OverrideprotectedvoiddoGet(HttpServletRequest req,HttpServletResponse resp){HttpSession session = req.getSession(false);if(session !=null){ session.invalidate();// 销毁 Session} resp.getWriter().println("已退出登录");}}

📌 四、Spring Boot 中使用 Session

4.1 启用 Session 支持(默认已开启)

@RestControllerpublicclassUserController{@PostMapping("/login")publicStringlogin(@RequestParamString username,HttpServletRequest request){HttpSession session = request.getSession(); session.setAttribute("username", username);return"登录成功,用户:"+ username;}@GetMapping("/info")publicStringgetUserInfo(HttpServletRequest request){HttpSession session = request.getSession(false);if(session !=null&& session.getAttribute("username")!=null){return"当前用户:"+ session.getAttribute("username");}return"未登录";}@GetMapping("/logout")publicStringlogout(HttpServletRequest request){HttpSession session = request.getSession(false);if(session !=null){ session.invalidate();}return"已退出";}}

4.2 使用 @SessionAttribute 注解(更优雅)

@Controller@SessionAttributes("user")publicclassSessionController{@PostMapping("/login")publicStringlogin(@RequestParamString username,Model model){ model.addAttribute("user",newUser(username));return"redirect:/dashboard";}@GetMapping("/dashboard")publicStringdashboard(@SessionAttribute("user")User user,Model model){ model.addAttribute("user", user);return"dashboard";}}

📌 五、Session 的注意事项与最佳实践

5.1 安全性问题

风险解决方案
Session 劫持使用 HTTPS、设置 SecureHttpOnly Cookie
Session 固定攻击登录成功后调用 session.invalidate() 并创建新 Session
Session 泄露敏感信息不要存入 Session(如密码)
// 在 Spring Boot 中配置 server.servlet.session.cookie.http-only=true server.servlet.session.cookie.secure=true server.servlet.session.cookie.same-site=strict 

5.2 性能与可扩展性

  • 内存占用:Session 默认存储在服务器内存中,大量用户会消耗内存。
  • 集群部署问题:多台服务器时,Session 无法共享。
解决方案:
  • 使用 Redis 存储 Session(推荐)
  • 使用 Spring Session + Redis
<!-- pom.xml --><dependency><groupId>org.springframework.session</groupId><artifactId>spring-session-data-redis</artifactId></dependency>
# application.ymlspring:session:store-type: redis redis:host: localhost port:6379

5.3 Session 过期时间

# application.ymlserver:servlet:session:timeout: 30m # 30分钟

或在代码中设置:

session.setMaxInactiveInterval(1800);// 秒

✅ 总结

项目说明
Session 本质服务器端状态保持机制
核心原理通过 Session ID 识别用户
优点简单易用、数据安全(不暴露给客户端)
缺点占用服务器资源、集群部署需共享
最佳实践使用 Redis 存储、设置合理过期时间、防止 Session 劫持
替代方案JWT(无状态认证)

📚 推荐

Read more

SAM 3开源大模型部署教程:Docker镜像+Jupyter+Web三模式详解

SAM 3开源大模型部署教程:Docker镜像+Jupyter+Web三模式详解 1. 为什么你需要SAM 3——不只是分割,而是理解视觉内容 你有没有遇到过这样的问题:想从一张杂乱的街景图里快速抠出所有行人,或者从一段监控视频中持续追踪某个包裹?传统方法要么需要大量标注数据,要么得写一堆OpenCV规则,费时又难泛化。SAM 3不一样——它不靠预设规则,而是像人一样“看懂”画面:你点一下、框一下,甚至只说一句“那个穿红衣服的人”,它就能立刻识别、分割、跟踪。 这不是概念演示,而是已经能跑在你本地机器上的真实能力。SAM 3是Meta(Facebook)推出的统一基础模型,专为图像和视频中的可提示分割设计。它把检测、分割、跟踪三个任务融合进一个模型,支持文本提示(如“cat”、“bicycle”)、点提示(单击目标区域)、框提示(拖拽包围目标)、掩码提示(粗略涂鸦)等多种交互方式。

使用 OpenVINO 本地部署 DeepSeek-R1 量化大模型(第二章:前端交互与后端服务)

使用 OpenVINO 本地部署 DeepSeek-R1 量化大模型(第二章:前端交互与后端服务)

一、前言         基于上一章的环境准备和模型转换,本章专注于后端服务器的部署以及前端页面的启动。 使用 OpenVINO 本地部署 DeepSeek-R1 量化大模型(第一章:基础概念与模型转换)-ZEEKLOG博客https://blog.ZEEKLOG.net/plmm__/article/details/156192071?spm=1001.2014.3001.5502         整个后端服务器是依赖于 OpenVINO 的,不过只要你的设备可以使用 OpenVINO,理论上就可以使用这个后端,如果你有 intel 的独立显卡,只需要把代码中 device 更改为对应的设备即可运行在 GPU 上。 self.pipeline = ov_genai.LLMPipeline(self.model_path, device) 二、前端交互界面          网页预览:

小白前端别慌:30分钟搞懂CSS渐变,让你的按钮秒变高级感!

小白前端别慌:30分钟搞懂CSS渐变,让你的按钮秒变高级感!

小白前端别慌:30分钟搞懂CSS渐变,让你的按钮秒变高级感! * 小白前端别慌:30分钟搞懂CSS渐变,让你的按钮秒变高级感! * 为啥你的页面看起来像2003年的? * CSS渐变到底是个啥玩意儿 * 线性渐变:方向这东西,比你想的会玩 * 最基础的写法 * 方向控制:关键字、角度、甚至斜着来 * 多颜色停点:不止两个色,想停哪停哪 * 透明渐变:rgba和透明通道的妙用 * 实战:做一个会呼吸的按钮 * 径向渐变:从中心炸开的光晕美学 * 基础语法:圆心、形状、大小 * 颜色停点同样适用 * 实战:做一个发光输入框 * 别被语法吓跑:咱们拆解一下那些参数 * 方向到底怎么算? * 颜色停点的三种写法 * 透明度渐变的高级玩法 * 多层渐变叠加:背景图能塞好几个? * 性能会不会崩? * 浏览器兼容:Safari又抽风了? * 加前缀的日子基本过去了 * Safari的奇葩bug *

Claude+Android Studio联动开发:我是如何用AI助手10分钟搞定WebView项目模板的

Claude+Android Studio联动开发:我是如何用AI助手10分钟搞定WebView项目模板的 上周三下午,产品经理突然丢过来一个需求:“下周一要演示一个内嵌H5页面的App原型,能不能先搭个架子?”我看了眼时间,距离下班只剩两小时。要在这么短的时间内从零开始搭建一个完整的Android WebView项目,还要处理好权限声明、Gradle依赖、网络配置这些琐碎但容易出错的部分,换作以前我肯定要加班到深夜。 但这次,我只用了十分钟。 不是因为我手速快,而是因为我找到了一个全新的工作流——让Claude这个AI助手帮我处理那些重复性的配置工作。整个过程就像有个经验丰富的搭档在旁边,你只需要告诉他你想要什么,他就能把代码、配置、甚至最佳实践建议都准备好。 如果你也在Android开发中遇到过类似的情况:每次新建项目都要反复查阅文档,担心漏掉某个关键权限,或者被Gradle版本兼容性问题搞得焦头烂额,那么这篇文章就是为你准备的。我会详细拆解如何通过自然语言指令,让Claude生成一个完整、可运行的WebView模块,并且补充那些官方文档很少提及的组件化实践细节。 1.