💎一站式轻松地调用各大LLM模型接口,支持GPT4、智谱、星火、月之暗面及文生图 广告
Cookie 和 Session 都为了用来保存状态信息,都是保存客户端状态的机制,它们都是为了解决HTTP无状态的问题而所做的努力。 * Cookie机制 简单地说,Cookie 就是浏览器储存在用户电脑上的一小段文本文件。Cookie 是纯文本格式,不包含任何可执行的代码。 一个 Web 页面或服务器告知浏览器按照一定规范来储存这些信息,并在随后的请求中将这些信息发送至服务器,Web 服务器就可以使用这些信息来识别不同的用户。 大多数需要登录的网站在用户验证成功之后都会设置一个 Cookie,只要这个 Cookie 存在并可以,用户就可以自由浏览这个网站的任意页面。 Cookie 会被浏览器自动删除,通常存在以下几种原因: 1. 会话 Cooke (Session Cookie) 在会话结束时(浏览器关闭)会被删除 2. 持久化 Cookie(Persistent Cookie)在到达失效日期时会被删除 3. 如果浏览器中的 Cookie 数量达到限制,那么 Cookie 会被删除以为新建的 Cookie 创建空间。 大多数浏览器支持最大为 4096 字节的 Cookie。由于这限制了 Cookie 的大小,最好用 Cookie 来存储少量数据,或者存储用户 ID 之类的标识符。 用户 ID 随后便可用于标识用户,以及从数据库或其他数据源中读取用户信息。 浏览器还限制站点可以在用户计算机上存储的 Cookie 的数量。 大多数浏览器只允许每个站点存储 20 个 Cookie;如果试图存储更多 Cookie,则最旧的 Cookie 便会被丢弃。 有些浏览器还会对它们将接受的来自所有站点的 Cookie 总数作出绝对限制,通常为 300 个。 使用 Cookie 的缺点: 1. 不良站点用 Cookie 收集用户隐私信息; 2. Cookie窃取:黑客以可以通过窃取用户的cookie来模拟用户的请求行为。(跨站脚本攻击XSS) 3. Session 机制 Session机制是一种服务器端的机制,服务器使用一种类似于散列表的结构(也可能就是使用散列表)来保存信息。当程序需要为某个客户端的请求创建一个session的时候,服务器首先检查这个客户端的请求里是否已包含了一个Session标识(Session id). 如果已包含一个SessionID 则说明以前已经为此客户端创建过Session,服务器就按照SessionID把这个 Session检索出来使用(如果检索不到,可能会新建一个)。 如果客户端请求不包含SessionID,则为此客户端创建一个Session并且生成一个与此Session相关联的SessionID,SessionID的值应该是一个既不会重复,又不容易被找到规律以仿造的字符串,这个SessionID将被在本次响应中返回给客户端保存。 具体实现方式: * Cookie方式 服务器给每个Session分配一个唯一的JSESSIONID,并通过Cookie发送给客户端。 当客户端发起新的请求的时候,将在Cookie头中携带这个JSESSIONID,这样服务器能够找到这个客户端对应的Session。 * URL回写 服务器在发送给浏览器页面的所有链接中都携带JSESSIONID的参数,这样客户端点击任何一个链接都会把JSESSIONID带回服务器。如果直接在浏览器输入服务端资源的url来请求该资源,那么Session是匹配不到的。 Web 缓存: WEB缓存(cache)位于Web服务器和客户端之间,缓存机制会根据请求保存输出内容的副本,例如html页面,图片,文件,当下一个请求来到的时候:如果是相同的URL,缓存直接使用副本响应访问请求,而不是向源服务器再次发送请求。 主要分三种情况: 1. 未找到缓存(黑色线):当没有找到缓存时,说明本地并没有这些数据,这种情况一般发生在我们首次访问网站,或者以前访问过,但是清除过缓存后。 浏览器就会先访问服务器,然后把服务器上的内容取回来,内容取回来以后,就要根据情况来决定是否要保留到缓存中了。 2. 缓存未过期(蓝色线):缓存未过期,指的是本地缓存没有过期,不需要访问服务器了,直接就可以拿本地的缓存作为响应在本地使用了。这样节省了不少网络成本,提高了用户体验过。 3. 缓存已过期(红色线):当满足过期的条件时,会向服务器发送请求,发送的请求一般都会进行一个验证,目的是虽然缓存文档过期了,但是文档内容不一定会有什么改变,所以服务器返回的也许是一个新的文档,这时候的HTTP状态码是200,或者返回的只是一个最新的时间戳和304状态码。 缓存过期后,有两种方法来判定服务端的文件有没有更新。 第一种在上一次服务端告诉客户端约定的有效期的同时,告诉客户端该文件最后修改的时间,当再次试图从服务端下载该文件的时候,check下该文件有没有更新(对比最后修改时间),如果没有,则读取缓存. 第二种方式是在上一次服务端告诉客户端约定有效期的同时,同时告诉客户端该文件的版本号,当服务端文件更新的时候,改变版本号,再次发送请求的时候check一下版本号是否一致就行了,如一致,则可直接读取缓存。 浏览器是依靠请求和响应中的的头信息来控制缓存的,如下: * Expires与Cache-Control:服务端用来约定和客户端的有效时间的。 Expires规定了缓存失效时间(Date为当前时间),而`Cache-Control`的max-age规定了缓存有效时间(2552s)。 Expires是HTTP1.0的东西,而`Cache-Control`是HTTP1.1的,规定如果`max-age`和Expires同时存在,前者优先级高于后者。 * Last-Modified/If-Modified-Since缓存过期后,check服务端文件是否更新的第一种方式。 * ETag/If-None-Match:缓存过期时check服务端文件是否更新的第二种方式。 实际上ETag并不是文件的版本号,而是一串可以代表该文件唯一的字符串,当客户端发现和服务器约定的直接读取缓存的时间过了,就在请求中发送If-None-Match选项,值即为上次请求后响应头的ETag值. 该值在服务端和服务端代表该文件唯一的字符串对比(如果服务端该文件改变了,该值就会变),如果相同,则相应HTTP304,客户端直接读取缓存,如果不相同,HTTP200,下载正确的数据,更新ETag值。 当然并不是所有请求都能被缓存。无法被浏览器缓存的请求: 1. HTTP信息头中包含`Cache-Control:no-cache,pragma:no-cache(HTTP1.0)`,或`Cache-Control:max-age=0`等告诉浏览器不用缓存的请求 2. 需要根据Cookie,认证信息等决定输入内容的动态请求是不能被缓存的 3. POST请求无法被缓存 浏览器缓存过程还和用户行为有关。譬如先打开一个主页有个jquery的请求(假设访问后会缓存下来)。 接着如果直接在地址栏输入 jquery 地址,然后回车,响应HTTP200(from cache),因为有效期还没过直接读取的缓存;如果`ctrl+r`进行刷新,则会相应HTTP304(Not Modified),虽然还是读取的本地缓存,但是多了一次服务端的请求;而如果是ctrl+shift+r强刷,则会直接从服务器下载新的文件,响应HTTP200。