【JavaEE进阶】Cookie和Session详解

目录

什么是Cookie

什么是Session

Cookie和Session的区别

获取Cookie

传统获取Cookie

简洁获取Cookie

Session的存取

Session存储

Session读取

传统方式获取

简洁获取Session(1)

简洁获取Session(2)


会话(Session)跟踪是 Web 程序中常用的技术,用来跟踪用户的整个会话 。常用的会话跟踪技术是 Cookie 与 Session 。Cookie通过在客户端记录信息确定用户身份Session通过在服务器端记录信息确定用户身份 。这篇文章我们就来详细了解一下Cookie 与 Session.

什么是Cookie

Cookie 是服务器传给客户端的体积很小的纯文本文件。客户端请求服务器,如果服务器需要记录该用户状态,就向客户端浏览器发一个 Cookie 。客户端浏览器会把 Cookie 保存起来。当浏览器再请求该网站时,浏览器把请求的网址连同该 Cookie 一同提交给服务器。服务器检查该 Cookie ,以此来辨认用户状态。

HTTP协议自身是属于"无状态"协议.

"无状态"的含义指的是:

默认情况下 HTTP 协议的客户端和服务器之间的这次通信,和下次通信之间没有直接的联系.

但是实际开发中,我们很多时候是需要知道请求之间的关联关系的. 例如登陆网站成功后,第二次访问的时候服务器就能知道该请求是否是已经登陆过了.

比如去医院挂号

  1. 看病之前先挂号.挂号时候需要提供身份证号,同时得到了一张"就诊卡",这个就诊卡就相当于患者的"令牌".

  2. 后续去各个科室进行检查, 诊断,开药等操作,都不必再出示身份证了,只要凭就诊卡即可识别出当前患者的身份.

  3. 看完病了之后,不想要就诊卡了,就可以注销这个卡.此时患者的身份和就诊卡的关联就销毁了. (类似于网站的注销操作)

  4. 又来看病, 可以办一张新的就诊卡, 此时就得到了一个新的 "令牌"

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

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

什么是Session

Session 是另一种记录客户状态的机制,不同的是 Cookie 保存在客户端浏览器中,而 Session 保存在服务器上。客户端浏览器访问服务器的时候,服务器把客户端信息以某种形式记录在服务器上,这就是 Session。客户端浏览器再次访问时只需要从该 Session 中查找该客户的状态就可以了。Session 相当于程序在服务器上建立的一份用户的档案,用户来访的时候只需要查询用户档案表就可以了。

理解Session

我们先来了解一下什么是会话.

会话:对话的意思

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

比如我们打客服电话

每次打客服电话, 是一个会话. 挂断电话, 会话就结束了

下次再打客服电话, 又是一个新的会话.

如果我们长时间不说话,没有新的请求, 会话也会结束.

服务器同一时刻收到的请求是很多的. 服务器需要清楚的区分每个请求是从属于哪个用户,也就是属于哪个会话,就需要在服务器这边记录每个会话以及与用户的信息的对应关系.

Session 是服务器为了保存用户信息而创建的一一个特殊的对象.

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

Sessionld是由服务器生成的一个"唯一性字符串", 从Session机制的角度来看, 这个唯一性字符串称

为" Sessionld". 但是站在整个登录流程中看待,也可以把这个唯一性字符串称为 "token".

上述例子中的令牌ID, 就可以看做是Sessionld 只不过令牌除了ID之外, 还会带一些其他信息, 比如时间, 签名等.

1.当用户登陆的时候, 服务器在 Session 中新增一个新记录, 并把 Sessionld 返回给客户端. (通过
HTTP 响应中的 Set-Cookie 字段返回).

2.客户端后续再给服务器发送请求的时候,需要在请求中带上Sessionld. (通过HTTP请求中的
Cookie 字段带上).

3.服务器收到请求之后,根据请求中的 Sessionld 在 Session 信息中获取到对应的用户信息, 再进行后续操作找不到则重新创建 Session, 并把 Sessionld 返回

Session 默认是保存在内存中的. 如果重启服务器则 Session 数据就会丢失.

Cookie和Session的区别

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

  2. Cookie 和Session之间主要是通过Sessionld关联起来的,Sessionld是Cookie和Session之间的

桥梁

  1. Cookie 和Session经常会在一起配合使用.但是不是必须配合.
  • 完全可以用 Cookie 来保存一些数据在客户端.这些数据不一定是用户身份信息,也不一定是Sessionld.
  • Session 中的 Sessionld 也不需要非得通过Cookie/Set-Cookie传递,比如通过URL传递.
  1. Session 能够存储任意的 java 对象,Cookie 只能存储 String 类型的对象

  2. Session 比 Cookie 更具有安全性(Cookie 有安全隐患,通过拦截或本地文件找得到你的 Cookie 后可以进行攻击)

  3. Session占用服务器性能,Session过多,增加服务器压力

  4. 单个Cookie 保存的数据不能超过4K,很多浏览器都限制一个站点最多保存20个Cookie , Session 是没有大小限制和服务器的内存大小有关。

获取Cookie

传统获取Cookie

Spring MVC 是基于Servlet API构建的原始 Web 框架,也是在 Servlet 的基础上实现的HttpServletRequest ,HttpServletResponse 是 Servlet 提供的两个类, 是 Spring MVC 方法的内置对象.需要时直接在方法中添加声明即可.

HttpServletRequest 对象代表客户端的请求,当客户端通过 HTTP 协议访问服务器时,HTTP 请求头中的所有信息都封装在这个对象中,通过这个对象提供的方法,可以获得客户端请求的所有信息.

HttpServletResponse 对象代表服务器的响应. HTTP 响应的信息都在这个对象中,比如向客户

端发送的数据, 响应头, 状态码等. 通过这个对象提供的方法,可以获得服务器响应的所有内容

Spring MVC 在这两个对象的基础上进行了封装, 给我们提供更加简单的使用方法.

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

我们手动设置一下Cookie的值:

通过浏览器访问测试:

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

简洁获取Cookie

也有更简洁的方式获取Cookie

java 复制代码
    @RequestMapping("/getCookie")
    public String getCookie(@CookieValue("zhangsan") String value) {
        return "zhangsan:" + value;
    }

通过浏览器访问测试:

对应关系:

Session的存取

Session 是服务器端的机制, 我们需要先存储, 才能再获取

Session 也是基于 HttpServletRequest 来存储和获取的

Session存储

java 复制代码
    @RequestMapping("/setSess")
    public String setSess(HttpServletRequest request) {
        //获取Session对象
        HttpSession session = request.getSession();
        if(session!=null) {
            session.setAttribute("username","java");
        }
        return "session 存储成功";
    }

session 存储的值可以是任意java对象:

这个代码中看不到 Sessionld 这样的概念的. getSession 操作内部提取到请求中的 Cookie 里的
Sessionld , 然后根据 Sessionld 获取到对应的 Session 对象, Session 对象用 HttpSession 来描述.

获取Session有两种方式

java 复制代码
HttpSession getSession(boolean create);

HttpSession getSession();

HttpSession getSession(boolean create): 参数如果为 true, 则当不存在会话时新建会话;参数如果为 false ,则当不存在会话时返回 null

HttpSession getSession(): 和 getSession(true) 含义一样, 默认值为 true.

void setAttribute(String name, Object value): 使用指定的名称绑定一个对象 到该session会话

Session读取

传统方式获取

读取 Session 可以使用 HttpServletRequest

java 复制代码
    @RequestMapping("/getSess")
    public String sess(HttpServletRequest request) {
        //如果 session 不存在, 不会自动创建
        HttpSession session = request.getSession(false);
        String username = null;
        if(session != null && session.getAttribute("username")!=null) {
            username = (String) session.getAttribute("username");
        }
        return "username:" + username;
    }

通过浏览器访问测试: (测试前需要先存储session)


Object gettribute(String name): 返回在该 session 会话中具有指定名称的对象,如果没有指定名

称的对象,则返回 null.

简洁获取Session(1)

java 复制代码
    @RequestMapping("/getSess2")
    public String sess2(@SessionAttribute(value = "username", required = false) String username) {
        return "username:" + username;
    }

简洁获取Session(2)

通过Spring MVC内置对象HttpSession来获取

java 复制代码
    @RequestMapping("/getSess3")
    public String sess3(HttpSession session) {
        String username = (String) session.getAttribute("username");
        return "username:" + username;
    }

HttpSession session = request.getSession();

Session 不存在的话,会自动进行创建

相关推荐
WTT001130 分钟前
2024楚慧杯WP
大数据·运维·网络·安全·web安全·ctf
苹果醋338 分钟前
React源码02 - 基础知识 React API 一览
java·运维·spring boot·mysql·nginx
晓纪同学1 小时前
QT-简单视觉框架代码
开发语言·qt
威桑1 小时前
Qt SizePolicy详解:minimum 与 minimumExpanding 的区别
开发语言·qt·扩张策略
Hello.Reader1 小时前
深入解析 Apache APISIX
java·apache
飞飞-躺着更舒服1 小时前
【QT】实现电子飞行显示器(简易版)
开发语言·qt
杨德杰1 小时前
QT网络(一):主机信息查询
网络·qt
明月看潮生1 小时前
青少年编程与数学 02-004 Go语言Web编程 16课题、并发编程
开发语言·青少年编程·并发编程·编程与数学·goweb
明月看潮生1 小时前
青少年编程与数学 02-004 Go语言Web编程 17课题、静态文件
开发语言·青少年编程·编程与数学·goweb
Java Fans1 小时前
C# 中串口读取问题及解决方案
开发语言·c#