「Spring MVC」Session、Cookie

🎇个人主页Ice_Sugar_7

🎇所属专栏JavaEE

🎇欢迎点赞收藏加关注哦!

Spring MVC

  • [🍉Session & Cookie](#🍉Session & Cookie)
  • [🍉获取 Cookie](#🍉获取 Cookie)
  • [🍉存储 & 获取 Session](#🍉存储 & 获取 Session)
  • [🍉获取 Header](#🍉获取 Header)

首先了解一下什么是会话

计算机领域中, 会话指的是一个客户端与服务器之间不中断的请求响应,对于客户端的请求,服务器能够知道这些请求都来自于同个客户
当一个未知的客户向 Web 应用程序发送第一个请求时,会话就开始了
当客户明确结束会话或服务器在一个时限内没有接收到该客户的任何请求时,会话就结束了

服务器在同一时刻会收到很多请求,此时就需要区分每个请求来自哪个客户, 也就是属于哪个会话, 这就需要服务器记录每个会话、与客户的信息的对应关系
Session 是服务器为了保存用户信息而创建的特殊的对象

Session 本质是一个哈希表, 存储了一些键值对。其中 Key 就是 SessionID,Value 就是用户信息(用户信息可以根据需求灵活设计)

  1. 用户登录时, 服务器在 Session 中新增一个记录, 并把 sessionId 返回给客户端 (通过 HTTP 响应中的 Set-Cookie 字段返回)
  2. 客户端后续再给服务器发送请求时, 需要在请求中带上 sessionId (通过 HTTP 请求中的 Cookie 字段带上
  3. 服务器收到请求之后, 根据请求中的 sessionId 在 Session 信息中获取到对应的用户信息, 再进行后续操作。若找不到,则重新创建 Session, 并返回 SessionID

说完 Session, 接下来回顾一下之前提过的 Cookie

首先我们需要知道, HTTP 协议是无状态的协议。无状态指的是 HTTP 协议的客户端和服务器之间的某次通信, 和下次通信之间没有直接联系

不过实际开发中, 我们很多时候需要知道请求之间的关联关系

比如成功登录网站后, 第二次访问的时候服务器就能知道该请求是否已经登录过,如果之前登录过,那就无需再次进入登录页面了,在这个过程中,浏览器和服务器进行如下的交互过程

上图提到的令牌通常存储在 Cookie 字段中, 令牌又称为 Token。前文提到的 SessionId 就是一种令牌


🍌联系与区别

Cookie 和 Session 之间主要通过 SessionId 关联起来

Cookie 是客户端保存用户信息的一种机制;Session 是服务器端保存用户信息的一种机制

二者通常会在⼀起配合使用,但不是必须配合。比方说,完全可以⽤ Cookie 把⼀些数据保存在客户端,这些数据不⼀定是用户⾝份信息, 也不⼀定是 SessionId。而 Session 中的 sessionId 也不是说一定得通过 Cookie/Set-Cookie 传递,还有别的传递方式,比如通过URL传递


先来认识 Servlet 提供的两个类:HttpServletRequestHttpServletResponse,它们是 Spring MVC 方法的内置对象

可将这两个类的对象分别视为是 HTTP 请求和响应封装成的对象,换而言之,HTTP 请求里面有啥,对应的 HttpServletRequest 对象里面就有啥。响应也是同理

代码如下:

java 复制代码
@RequestMapping("req11")
public String req11(HttpServletRequest request, HttpServletResponse response) {
    //获取所有 Cookie 的信息
    Cookie[] cookies = request.getCookies();
    //打印 Cookie 的信息
    StringBuilder sb = new StringBuilder();
    if(cookies != null)
        for(Cookie cookie : cookies)
            sb.append(cookie.getName() + ":" + cookie.getValue());
    return "Cookie 中的信息为:" + sb;
}

这个例子可以看出:Cookie 是可以伪造的, 也就是说不安全, 所以使用 Cookie 时, 后端需要校验 Cookie


🍉存储 & 获取 Session

由于 Session 存储在服务器中,所以我们需要先存储,然后才可以获取。它也是基于 HttpServletRequest 来存储和获取的

java 复制代码
HttpSession getSession()  //获取 Session,若不存在,则会新建一个 Session
void setAttribute(String name, Object value)  //使用指定名称绑定一个对象到该 Session 会话
java 复制代码
@RequestMapping("req12")
public String req12(HttpServletRequest request) {
    HttpSession session = request.getSession(); //获取 Session 对象
    if(session != null) session.setAttribute("username","zhangsan"); //把"zhangsan"这个对象绑定到 username 这个会话中
    return "session 存储成功";
}

getSession 操作内部会提取请求中 Cookie 的 SessionId, 然后根据 SessionId 获取到对应的 Session 对象

java 复制代码
Object getAttribute(String name) //返回该 Session 会话中具有指定名称的对象,如果没有,则返回 null
java 复制代码
@RequestMapping("req13")
public String req13(HttpServletRequest request) {
    HttpSession session = request.getSession(false); //如果 Session 不存在,不会自动创建一个,而是返回 null
    String username = null;
    if(session != null && session.getAttribute("username") != null)
        username = (String)session.getAttribute("username");
    return "username:" + username;
}

也可以通过 Spring MVC 内置对象 HttpSession 来获取,这种方式比较简洁


🍉获取 Header

Header 也是从 HttpServletRequest 中获取,使用 getHeader 方法

java 复制代码
@RequestMapping("req15")
public String req15(HttpServletRequest request) {
    String userAgent = request.getHeader("User-Agent");
    return "userAgent:" + userAgent;
}

浏览器运行结果:

使用 Fiddler 抓包观察 UserAgent 是否正确

同样也有简洁的办法获取 Header:

java 复制代码
@RequestMapping("req15")
public String req15(HttpServletRequest request) {
    String userAgent = request.getHeader("User-Agent");
    return "userAgent:" + userAgent;
}

相关推荐
尘浮生4 分钟前
Java项目实战II基于微信小程序的电影院买票选座系统(开发文档+数据库+源码)
java·开发语言·数据库·微信小程序·小程序·maven·intellij-idea
hopetomorrow18 分钟前
学习路之PHP--使用GROUP BY 发生错误 SELECT list is not in GROUP BY clause .......... 解决
开发语言·学习·php
郑祎亦27 分钟前
Spring Boot 项目 myblog 整理
spring boot·后端·java-ee·maven·mybatis
不是二师兄的八戒27 分钟前
本地 PHP 和 Java 开发环境 Docker 化与配置开机自启
java·docker·php
小牛itbull27 分钟前
ReactPress vs VuePress vs WordPress
开发语言·javascript·reactpress
请叫我欧皇i36 分钟前
html本地离线引入vant和vue2(详细步骤)
开发语言·前端·javascript
闲暇部落39 分钟前
‌Kotlin中的?.和!!主要区别
android·开发语言·kotlin
爱编程的小生39 分钟前
Easyexcel(2-文件读取)
java·excel
本当迷ya40 分钟前
💖2025年不会Stream流被同事排挤了┭┮﹏┭┮(强烈建议实操)
后端·程序员
GIS瞧葩菜1 小时前
局部修改3dtiles子模型的位置。
开发语言·javascript·ecmascript