会话管理(Cookie与Session)

文章介绍了HTTP协议的无状态特性以及如何通过Cookie和Session来保持会话状态。Cookie作为客户端的标识,Session则是服务器端记录用户信息的方式。通过举例和代码示例解释了Cookie的设置与获取,以及Session的工作原理和重要性,特别强调了它们在登录态管理中的作用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

背景

    默认情况下HTTP请求是无状态的(可以对话,但是不知道在和谁对话,也就是 HTTP 协议的客户端和服务器之间的这次通信, 和下次通信之间没有直接的联系)。但是实际开发中, 我们很多时候是需要知道请求之间的关联关系的,为了知道在和谁对话,就有了 Cookies (相当于是一张会员卡,虽然我不知道你是谁,但是如果我看到了你携带的“会员卡”我就可以识别你的身份)和 Session (相当于是我的内部记忆,我在脑子里记得你的身份),登陆网站成功后, 第二次访问的时候服务器就能知道该请求是否是已经登陆过了

Cookie

 图中的 "令牌" 通常就存储在 Cookie 字段中.

举个例子:

1. 到了医院先挂号 . 挂号时候需要提供身份证 , 同时得到了一张 " 就诊卡 ", 这个就诊卡就相当于患
者的 " 令牌 ".
2. 后续去各个科室进行检查 , 诊断 , 开药等操作 , 都不必再出示身份证了 , 只要凭就诊卡即可识别
出当前患者的身份 .
3. 看完病了之后 , 不想要就诊卡了 , 就可以注销这个卡 . 此时患者的身份和就诊卡的关联就销毁
. ( 类似于网站的注销操作 )
4. 又来看病 , 可以办一张新的就诊卡 , 此时就得到了一个新的 " 令牌 "

此时在服务器这边就需要记录令牌信息, 以及令牌对应的用户信息, 这个就是 Session 机制所做的工作. 

下面我们来实现一下会员卡的办理

@WebServlet("/first-visit")
public class FirstVisitServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //第一次访问,需要办会员卡(Cookie)+准备专属的文件(session)
        //这个session对象就是你的专属服务柜,会员卡已经隐含在里面了,只是我们看不到
        HttpSession session = req.getSession(true);
        session.setAttribute("first-visit-at", new Date());

        resp.setCharacterEncoding("utf-8");
        resp.setContentType("text/plain");
        resp.getWriter().println("办理会员成功");

    }
}

启动服务器后,访问一下127.0.0.1:8080/first-visit,我们就可以从开发人员工具网络面板里看到响应标头带有set-Cookie,

以及可以看到应用程序里就会保存此Cookie

 

 当我们再次访问其他网站时请求头中就带有Cookie了

Session (理解会话机制 )

服务器同一时刻收到的请求是很多的 . 服务器需要清除的区分清楚每个请求是从属于哪个用户 , 就需要在服务器这边记录每个用户令牌以及用户的信息的对应关系.
在上面的例子中 , 就诊卡就是一张 " 令牌 ". 要想让这个令牌能够生效 , 就需要医院这边通过系统记录
每个就诊卡和患者信息之间的关联关系 .
会话的本质就是一个 " 哈希表 ", 存储了一些键值对结构 . key 就是令牌的 ID(token/sessionId), value 就是用户信息( 用户信息可以根据需求灵活设计 ).
sessionId 是由服务器生成的一个 " 唯一性字符串 ", session 机制的角度来看 , 这个唯一性字符串
称为 "sessionId". 但是站在整个登录流程中看待 , 也可以把这个唯一性字符串称为 "token".
sessionId token 就可以理解成是同一个东西的不同叫法 ( 不同视角的叫法 )

  • 当用户登陆的时候, 服务器在 Session 中新增一个新记录, 并把 sessionId / token 返回给客户端.(例 如通过 HTTP 响应中的 Set-Cookie 字段返回).
  • 客户端后续再给服务器发送请求的时候, 需要在请求中带上 sessionId/ token. (例如通过 HTTP 请求中的 Cookie 字段带上).
  • 服务器收到请求之后, 根据请求中的 sessionId / token Session 信息中获取到对应的用户信息,再进行后续操作.
Servlet Session 默认是保存在内存中的 . 如果重启服务器则 Session 数据就会丢失 .
代码示例:
如果我们想要查看自己Cookie建立的时间
响应的内容注册时间
1.查看访问者是否是会员(查看是否有专属的档案柜)
   HttpSession session = req.getSession(false);(返回false表示只查看不创建)
  if(session == null){
  (取不到档案,访问者不是会员)
}else{
(是会员)
}
2.查看当时的创建时间
Object o = session.getAttribute("first-visit-at");

Date date = (Date)o;

if(o == null){

(档案是有,但是没有存储创立时间)

}else{

(获取到了时间)

}

@WebServlet("/get-first-time")
public class GetFirstTimeServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setCharacterEncoding("utf-8");
        resp.setContentType("text/plain");
        HttpSession session = req.getSession(false);
        if (session == null){
            resp.getWriter().println("身份不符合");
            return;
        }else {
            Object o = session.getAttribute("first-visit-at");
            Date date = (Date) o;
            if (o == null){
                resp.getWriter().println("无创建时间的记载");
                return;
            }else {
                resp.getWriter().println(date);
                return;
            }
        }
    }
}

此时我们要先去办理会员卡,否则服务器会找不到档案

 会员卡办理成功

再次访问获取建立档案时间的页面,获取时间成功!

Cookie Session 的区别

  • Cookie 是客户端的机制. Session 是服务器端的机制.
  • Cookie Session 经常会在一起配合使用. 但是不是必须配合.
       1. 完全可以用 Cookie 来保存一些数据在客户端 . 这些数据不一定是用户身份信息 , 也不一定是
        token / sessionId(只是服务器和浏览器交换数据的凭证)
        eg.(建立Cookie)
@WebServlet("/only-set-cookie")
public class OnlySetCookie extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        Cookie cookie1 = new Cookie("name", "jiaoer");
        resp.addCookie(cookie1);
        Cookie cookie2 = new Cookie("age", "18");
        resp.addCookie(cookie2);

    }
}
访问后,我们可以在应用中看到我们自己写入的Cookie
响应标头也带有我们自己设置的Cookie,以后在访问此服务器时我们的请求标头就会带有我们自己写入的Cookie
 

 若我们给Cookie设置过期时间,则name就会在到时间期限时消失,若我们不对过期时间进行设置,则过期时间就为此次会话,当进程结束Cookie就消失了。

  eg.(获取Cookie)
@WebServlet("/only-get-cookie")
public class OnlyGetCookie extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setCharacterEncoding("utf-8");
        resp.setContentType("text/plain");
        PrintWriter writer = resp.getWriter();
        Cookie[] cookies = req.getCookies();
        for (Cookie cookie : cookies) {
            System.out.println(cookie.getName() + "=" + cookie.getValue());

        }
    }
}
我们成功获取到了Cookie       

 当然我们也可以在浏览器的应用里手动加入Cookie

再次进行访问,我们也可以获取到手动输入的Cookie

       2.Session 中的 token / sessionId 也不需要非得通过 Cookie / Set-Cookie 传递 .
总之:
  1.Cookie是HTTP协议相关的,属于 浏览器 和 服务器 之间的事情
    浏览器的职责就是帮我们保存好Cookie,需要在之后的请求中携带Cookie
    服务器的职责就是设置Cookie(种Cookie)
    表现在HTTP协议上:
      请求头:Cookie:
      响应头:set-Cookie
  2.Session是服务器内部的事情,为每个会话准备了一个独立的Key - Value 结构,通过Session-id来区分,一般把Session-id放在Cookie中,利用Cookie的机制来传递。
  3.Cookie是个独立的机制,本身还有一些属性:过期时间,域名,路径....
  4.Cookie和Session最主要的功能是用作登录态管理的

核心方法

HttpServletRequest 类中的相关方法

HttpServletResponse 类中的相关方法

HttpSession 类中的相关方法
一个 HttpSession 对象里面包含多个键值对 . 我们可以往 HttpSession 中存任何我们需要的信息 .

Cookie 类中的相关方法
每个 Cookie 对象就是一个键值对 .

  • HTTP Cooke 字段中存储的实际上是多组键值对. 每个键值对在 Servlet 中都对应了一个 Cookie 对象.
  • 通过 HttpServletRequest.getCookies() 获取到请求中的一系列 Cookie 键值对.
  • 通过 HttpServletResponse.addCookie() 可以向响应中添加新的 Cookie 键值对

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值