【web】Session是什么又和cookie有啥关系

by img Microanswer Create at:Dec 30, 2019 9:50:05 AM 

Tags: web session cookie http html 网站



重要声明:本文章仅仅代表了作者个人对此观点的理解和表述。读者请查阅时持自己的意见进行讨论。

废话不多说,直接上正文。

——不是鲁迅说的。

一、Session

无论你是Java作为后台,PHP作为后台,.Net 作为后台你都可以发现有一个方法可以获取Session这玩意儿。这或许就是你接触Session开始的地方。由于笔者本人对于Java更为熟悉,因此将在java基础上进行讲解,实际上原理都是一样的,不必担心存在隔阂。

1、Session是什么

Session是存在于服务器端的。 你千万不要想着Session在浏览器里,它在服务器端也是你能够在后端的程序里通过代码获取Session最好的证据。细心的你肯定发现了,前端js代码里根本就不会有获取Session相关的方法。

Session就是一个键值对容器。 是的,它没有你想象中的那么复杂,它就是让你从里面获取数据,或则你放数据在里面的一个容器。而这个容器只不过维护着自己独有的存活期。而通常情况下你不必关系这件事情。除非你有自己的功能实现需求在这一块上面。

2、Sesison干嘛的

你一定有过这样的经历,你打开某宝网站想要购物了,提示你登录,然后你就登录了。没过一会儿,你又不想买了,把浏览器也给关闭了。但是又过了一会儿,你再次打开某宝网站,你发现你上次登录的状态还在,并没有要你再一次进行登录。

这就是因为你访问某宝时,某宝从Session里获取到了你之前的登录信息(之前登录时会将信息保存在session),所以这次你就不必再进行登录了。这无疑给用户带来了更好的体验感受。所以,Session既然是一个键值对容器,它就是拿来存一些数据的,通过这些缓存的数据,实现为用户带来更方便操作感受。

3、Session怎么产生的

Session的产生不是单独的,它必须和Cookie协同工作,为了更好的理解,这部分内容将在介绍完了Cookie后进行一同讲解。

二、Cookie

说得笼统点,Cookie就是一个HTTP请求里的Header里面的一个键值。在发起HTTP请求时,在Header里面添加一个名为 cookie 的键,里面的值就是会上传给服务端的cookie值。你既可以在客户端指定请求时要带上什么样的Cookie内容,也可以在响应时告诉客户端有哪些cookie会下发。你还需要注意,对于浏览器,浏览器总是会自动处理cookie,浏览器总是会自动将上次响应的cookie自动带入到下次请求中(仅仅会把同域的cookie带上,例如:aa.com下发的cookie,浏览器在下次访问aa.com时会带上这次下发的cookie。而不会把aa.com的cookie带到bb.com上去)。

Cookie的却是上述所说的。但显然不能只了解这点内容,为了让web服务更好的工作,它还有一定的规则定义在里面。

1、Cookie的格式

不得不说Cookie的格式是一种很奇葩的存在(不含贬义)。这里我特指的是在传输过程中的表现格式,而不是cookie本身的定义格式。那么下面我们慢慢道来:

2、响应Cookie的数据格式

几乎大多数的请求响应里都会包含Cookie值,不过需要你注意的是,响应里的cookie值,它的不是cookie,而是set-cookie,而且,特么的如果有多个cookie在响应里面,不是在同一个set-cookie键里面通过某特定字符分开,而是在响应头里面会有多个set-cookie键,每个后面跟着一个不同的cookie内容。下面是一份请求响应示列:

这是一份使用<postman>工具进行请求百度从而获取到的请求和响应日志。可以看到,红色线框区域内,百度服务端给我们响应了4个cookie。这样看来,对cookie响应的格式就非常清晰了。下面介绍一下Cookie本身的定义格式含义:

3、Cookie的格式

Cookie有几个固有字段的定义,它们分别如下:

字段含义
expires表示此cookie的过期时间,这是一个时间值,过了这个时间,就不应该再把此cookie提交到服务端了。
max-age表示此cookie的过期时间,这是一个时间段值,请求时间+maxAge = 实际过期的时间。
path表示此cookie能在哪些路径下提交到服务端
domain表示此cookie能提交给哪些域或子域名下
version表示版本号
comment描述,相当于一个对cookie的注释
secure表示此cookie只能在https的请求中被提交
httponly表示此cookie只能在响应和请求中传递,不能将此cookie暴露给开发者操作。也就说明了不能在JavaScript里面获取这样的cookie。
samesite为了防止 CSRF 攻击和用户追踪,有关此项请点击Cookie 的 SameSite 属性查看详情

在响应数据里,这些字段都是通过;号来间隔各个字段属性。把这些字段去除,剩下的就是cookie本身的键值内容了。

例如:上图中的cookie本身键值内容则是:

BD_NOT_HTTPS=1
BIDUPSID=ED2D87A3418138376C6A292B1702A386
PSTM=1577674617
BAIDUID=ED2D87A341813837A5C1FDA5B3D5B76E:FG=1

4、请求Cookie的格式

通过上面的分析,我们拿到了实际上cookie要传递的键值对内容。那么在下次请求时,就要带上这些cookie,这是http协议规定如此的。不过具体请求时要传递哪些内容,又受到了Cookie本身固有字段的各种值的限定。假设我们现在已经拿到了上述cookie,那么在下次提交请求时,则需要将Cookie这样提交:

上图红色线框中就是提交的cookie,可以看到它和响应时的cookie风格不太一样,甚至大不一样。不再是一个cookie一条数据,而是将所有的cookie值,根据cookie自身固定属性判断后,通过;号分割各个cookie,然后拼接成一个整体,将这个整体以header中的cookie这个键提交上去。

响应结果里百度服务端又给我们响应了新的cookie内容,这时候就应该再次保存这些新的cookie,留给下次使用。

从这里也可以看出,要从一个请求(request)里获取cookie,怎么获取?直接从header中取cookie这个键,拿到的值就是客户端提交上来的第一手cookie值。

三、Session与Cookie的不谋而合

我们知道Cookie总是会被浏览器自动处理,下次自动提交。那么,为了更好的提供服务,如果后端能够将某用户的某次访问数据缓存下来,那么用户下次访问时这些缓存数据就必然会提供用户更加个性化和遍历的使用体验。这时候问题就来了,服务端要缓存用户的数据,首先服务端就要有一个东西来确定这部分缓存数据是对应这个用户的,才能正确的实现这个功能。而什么样的一种解决方案可以实现呢,没错,Cookie这玩意儿看起来很符合我们的需求。

当某个用户初次访问M网站时,浏览器由于以前从来没有访问过,所以没有任何cookie提交到M网站。当网站服务端发现没有Cookie,不得不新创建一个Session缓存区域,创建完成后M网站就会把用于确定这个Seesion唯一性的Id值放在响应的cookie里面,唉~~这不就会被浏览器自动保存了嘛,然后下次请求的时候,浏览器又总是自动将cookie提交的,自然而然的,就把服务端之前放在cookie里的ID值又给传到了服务端,当服务端发现cookie里面有一个id,就会去尝试获取对应的Session,这样一来,你的Session缓存区域不就又被获取到了,还是上次那个,缓存数据获取也变得轻松起来。

这样的逻辑过程似乎非常棒,不过又不得不让人产生疑问,难道这个Sesion就这样一直可以保存着,用户越来越多,被分配的Session不也就越来越多,哪有那么多内存呢。所以Session是有过期时间的。

四、Session的过期

通常来说,Sesison的过期时间是30分钟,不过这是可以修改的。这个过期时间的计时方式不是从创建Sesison开始计时,而是从最后一次访问这个Session开始计时。当Session过期了之后,服务端会自动又创建一个新的,然后将新的id放在cookie里。

五、总结

经过了这么多的解释,现在把这整篇文章归结为两个字,他就是:“会话”。这样的描述非常符合Session的作用和意图,它就像用户打开了网站,被认为开启了和服务端的一次“会话”。

我讲完了。

Full text complete, Reproduction please indicate the source. Help you? Not as good as one:
Comment(Comments need to be logged in. You are not logged in.)
You need to log in before you can comment.

Comments (0 Comments)