都 9102 年了,还问 Session 和 Cookie 的区别

2024-08-28 16:58
文章标签 区别 session cookie 9102

本文主要是介绍都 9102 年了,还问 Session 和 Cookie 的区别,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

1 前言

最近看了一些同学的面经,发现无论什么技术岗位,还是会问到 Session 和 Cookie 的区别。

所有学技术的同学都知道 Session 和 Cookie 函数怎么用,知道 Session 和 Cookie 的区别就是 Session 是储存在服务端的,Cookie 是存储在浏览器的。

但是实际上是什么东西,一些刚学习技术的同学估计还是模糊,我刚学 PHP 的时候,这种感觉特别明显。PHP 中 Session 和 Cookie 的操作只要操作 $_COOKIE 和 $_SESSION 数组就可以了,而且操作方式和功能一模一样,搞得我一脸懵逼。

最后,还是自己实现了一个 Session 操作类才恍然大悟,实质上就是两个不同的存储对象嘛。

2 Cookie

Cookie 的诞生是为了能让无状态的 HTTP 报文带上一些特殊的数据,让服务端能够辨识请求的身份。

对于 Cookie 的概念就不多说了,Cookie 说简单点就是浏览器上的一个 key-value 存储对象,通过开发者工具直接看到 Cookie 的内容(F12)

写入数据方式

Cookie 写入数据的方式是通过 HTTP 返回报文 Header 部分 Set-Cookie 字段来设置,一个带有写 Cookie 指令的的 HTTP 返回报文如下

HTTP/1.1 200 OK
Set-Cookie: SESSIONID=e13179a6-2378-11e9-ac30-fa163eeeaea1; Path=/
Transfer-Encoding: chunked
Date: Tue, 29 Jan 2019 07:12:09 GMT
Server: localhost

上述报文 Set-Cookie 指示浏览器设置 key 为 SESSIONIDvalue 为 e13179a6-2378-11e9-ac30-fa163eeeaea1 的 Cookie

获取数据方式

浏览器在发送请求的时候会检查当前域已经设置的 Cookie,在 HTTP 请求报文 Header 部分的 Cookie 字段里面带上 Cookie 的信息。下面捉取了一段 HTTP 报文

GET http://10.0.1.24:23333/ HTTP/1.1
Host: 10.0.1.24:23333
Connection: keep-alive
Pragma: no-cache
Cache-Control: no-cache
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.77 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9,en;q=0.8
Cookie: SESSIONID=e13179a6-2378-11e9-ac30-fa163eeeaea1

从最后的 Cookie 字段看到,浏览器请求时带上了 key 为 SESSIONIDvalue 为 e13179a6-2378-11e9-ac30-fa163eeeaea1 的数据,后端直接解析 HTTP 报文就能获取 Cookie 的内容。

 

3 Session

Session 在代码里面的语意是记录客户端状态的一个存储对象,是同一个客户端请求共享的数组。这个存储对象可以是文件、缓存系统、数据库。

现在假设要使用 redis 来实现 Session 功能,那么就要求浏览器每次请求都要带一个相同的字符串作为身份信息,对应 redis 的 key,redis value 则为 Session 数组序列化的内容。

那么如何让浏览器每次请求都带一个身份信息呢,这就是 Session 和 Cookie 的关系,通过 Cookie 传递这个身份信息。流程如下

  1. 客户端请求

  2. 服务端检查 Header,发现没有 Cookie,于是生成一个 UUID

  3. 服务端处理数据,把部分数据(登录信息)存储到 redis 里面,UUID 为 key,用户 id 为 value

  4. 返回报文中,增加 Set-Cookie 字段,内容带上 UUID

  5. 浏览器收到报文,把 UUID 写进浏览器存储里面

  6. 浏览器再次请求,带上当前的域的 Cookie,就是这个 UUID

  7. 服务端通过 Cookie 字段获取到该 UUID,去 redis 里面获取用户的信息

...

4 手动实现 Session

 

既然知道了 Session 的原理,我们手动实现一个 Session 操作类,采用文件保存的方式。http 框架采用 web.py,安装方式如下

 

pip install web.py

 

Session类

 

我们要实现的这个类就叫 Session

 

class Session:def __init__(self):self.session_id = None# session 数组self._items = dict()self._load()

 

我们所有 session 文件放在 sessions 目录下,文件名为对应的 session id,内容为 Session 数组序列化的字符串。在初始化对象的时候通过获取名为 SESSIONID 的 Cookie,如果没有就生成一个新的。

 

def _load(self):SESSIONID = web.cookies().get('SESSIONID', None)if not SESSIONID:SESSIONID = uuid.uuid()self.session_id = SESSIONIDself._loadFromDisk()

 

获取到 SESSIONID 后,检查 sessions 目录下有没有对应的文件,如果有就读取并反序列化

 

def _loadFromDisk(self):""" 从文件加载 SESSION """file = './sessions/%s' % self.session_idif os.path.exists(file):f = open(file, 'rb')self._items = pickle.load(f)f.close()

 

获取 Session 部分完成了,接下来就是保存 Session,我们要把 SESSIONID 写进 Cookie 里面,这样才能在下次请求时获取到对应的 SESSIONID

 

def _setSessionCookie(self):""" Session id 写入 cookie """web.setcookie('SESSIONID', self.session_id)

 

最后把 Session 的内容保存到文件里面

 

def _saveToDisk(self):""" 保存 SESSION 到文件 """f = open('./sessions/%s' % self.session_id, 'wb')pickle.dump(self._items, f)f.close()

 

功能测试

 

我们新建一个文件,叫 server.py,写入测试代码

 

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# 测试 sessionimport web
import time
from session import Sessionurls = ('/', 'index'
)app = web.application(urls, globals())class index:def GET(self):session = Session()if 'login_time' not in session:session['login_time'] = int(time.time())return 'login time: %s' % session['login_time']if __name__ == "__main__":app.run()

 

在同一目录新建 session.py 文件,写入 Session 类代码

 

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# Sessionimport os
import web
import uuid
try:import cPickle as pickle
except ImportError:import pickleclass Session:__instance = Nonedef __new__(cls):""" 单例模式 """if cls.__instance is None:cls.__instance = object.__new__(cls)return cls.__instanceelse:return cls.__instancedef __init__(self):self.session_id = None# session 数组self._items = dict()self._load()def __contains__(self, key):return key in self._itemsdef __getitem__(self, key):return self._items.get(key, None)def __setitem__(self, key, value):self._items[key] = valuereturn Truedef __delitem__(self, key):if key in self._items:del self._items[key]return Truedef __del__(self):""" 析构函数,结束请求时执行 """self._setSessionCookie()self._saveToDisk()def _load(self):SESSIONID = web.cookies().get('SESSIONID', None)if not SESSIONID or SESSIONID is None:SESSIONID = uuid.uuid()self.session_id = SESSIONIDself._loadFromDisk()def _loadFromDisk(self):""" 从文件加载 SESSION """file = './sessions/%s' % self.session_idif os.path.exists(file):f = open(file, 'rb')self._items = pickle.load(f)f.close()def _setSessionCookie(self):""" Session id 写入 cookie """web.setcookie('SESSIONID', self.session_id)def _saveToDisk(self):""" 保存 SESSION 到文件 """f = open('./sessions/%s' % self.session_id, 'wb')pickle.dump(self._items, f)f.close()

 

再在同一目录新建 sessions 目录,存放我们的 Session 文件

 

mkdir sessions

 

启动服务

 

[service@chengqm mysession]$ python server.py 23333
http://0.0.0.0:23333/

 

浏览器发起请求

查看 Cookie

 

 

查看 Session 文件内容

[service@chengqm mysession]$ cat sessions/e13179a6-2378-11e9-ac30-fa163eeeaea1
(dp1
S'login_time'
p2
I1548749002
s.

可以多次刷新和更换浏览器测试,测试结果是符合我们对 Session 的预期,简陋版 Session 类功能就算实现了。

 

5 如果禁止 Cookie 是否可以获取 Session

这是一道面试题,当年竟然能用这个问题问倒过一些朋友,还是有些意思的

从前面可以知道,SESSIONID 是通过 Cookie 来传递,如果 Cookie 禁止了,还能获取 SESSIONID 吗? 答案是可以的

既然 Cookie 禁止了,那么我们就可以用参数的方法传递 SESSIONID,后端返回的时候,增加一个返回参数,叫 SESSIONID,然后前端存储到 localstorage 里面

前端请求的时候,去 localstorage 获取SESSIONID,在请求参数里面增加这一个参数

后端 Session 处理,先尝试从 Cookie 中获取 SESSIONID,如果获取不到,再尝试从请求参数中获取 SESSIONID

这样,就算禁止 Cookie 也是能获取 Session 的。

6 总结

最后,我们得出 Session 和 Cookie 区别和联系

区别

  • Cookie 是浏览器端的存储对象,有容量限制,通过 HTTP 报文与后端交互

  • Session 是服务端的存储对象,实现的方式可以有文件系统、缓存系统、数据库

联系

  • Session 和 Cookie 都是为了实现 HTTP 请求带上客户端状态的方法

  • Session 大多数情况下都是依赖 Cookie 来传递 Session Id

这篇关于都 9102 年了,还问 Session 和 Cookie 的区别的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1115346

相关文章

native和static native区别

本文基于Hello JNI  如有疑惑,请看之前几篇文章。 native 与 static native java中 public native String helloJni();public native static String helloJniStatic();1212 JNI中 JNIEXPORT jstring JNICALL Java_com_test_g

Android fill_parent、match_parent、wrap_content三者的作用及区别

这三个属性都是用来适应视图的水平或者垂直大小,以视图的内容或尺寸为基础的布局,比精确的指定视图的范围更加方便。 1、fill_parent 设置一个视图的布局为fill_parent将强制性的使视图扩展至它父元素的大小 2、match_parent 和fill_parent一样,从字面上的意思match_parent更贴切一些,于是从2.2开始,两个属性都可以使用,但2.3版本以后的建议使

Collection List Set Map的区别和联系

Collection List Set Map的区别和联系 这些都代表了Java中的集合,这里主要从其元素是否有序,是否可重复来进行区别记忆,以便恰当地使用,当然还存在同步方面的差异,见上一篇相关文章。 有序否 允许元素重复否 Collection 否 是 List 是 是 Set AbstractSet 否

javascript中break与continue的区别

在javascript中,break是结束整个循环,break下面的语句不再执行了 for(let i=1;i<=5;i++){if(i===3){break}document.write(i) } 上面的代码中,当i=1时,执行打印输出语句,当i=2时,执行打印输出语句,当i=3时,遇到break了,整个循环就结束了。 执行结果是12 continue语句是停止当前循环,返回从头开始。

maven发布项目到私服-snapshot快照库和release发布库的区别和作用及maven常用命令

maven发布项目到私服-snapshot快照库和release发布库的区别和作用及maven常用命令 在日常的工作中由于各种原因,会出现这样一种情况,某些项目并没有打包至mvnrepository。如果采用原始直接打包放到lib目录的方式进行处理,便对项目的管理带来一些不必要的麻烦。例如版本升级后需要重新打包并,替换原有jar包等等一些额外的工作量和麻烦。为了避免这些不必要的麻烦,通常我们

ActiveMQ—Queue与Topic区别

Queue与Topic区别 转自:http://blog.csdn.net/qq_21033663/article/details/52458305 队列(Queue)和主题(Topic)是JMS支持的两种消息传递模型:         1、点对点(point-to-point,简称PTP)Queue消息传递模型:         通过该消息传递模型,一个应用程序(即消息生产者)可以

深入探讨:ECMAScript与JavaScript的区别

在前端开发的世界中,JavaScript无疑是最受欢迎的编程语言之一。然而,很多开发者在使用JavaScript时,可能并不清楚ECMAScript与JavaScript之间的关系和区别。本文将深入探讨这两者的不同之处,并通过案例帮助大家更好地理解。 一、什么是ECMAScript? ECMAScript(简称ES)是一种脚本语言的标准,由ECMA国际组织制定。它定义了语言的语法、类型、语句、

Lua 脚本在 Redis 中执行时的原子性以及与redis的事务的区别

在 Redis 中,Lua 脚本具有原子性是因为 Redis 保证在执行脚本时,脚本中的所有操作都会被当作一个不可分割的整体。具体来说,Redis 使用单线程的执行模型来处理命令,因此当 Lua 脚本在 Redis 中执行时,不会有其他命令打断脚本的执行过程。脚本中的所有操作都将连续执行,直到脚本执行完成后,Redis 才会继续处理其他客户端的请求。 Lua 脚本在 Redis 中原子性的原因

JavaScript中document.cookie

“某些 Web 站点在您的硬盘上用很小的文本文件存储了一些信息,这些文件就称为 Cookie。”—— MSIE 帮助。一般来说,Cookies 是 CGI 或类似,比 HTML 高级的文件、程序等创建的,但是 javascript 也提供了对 Cookies 的很全面的访问权利。       每个 Cookie 都是这样的:<cookie名>=<值>   <cookie名>的限制与 javasc

msys2 minggw-w64 cygwin wsl区别

1 mingw-w64,这是gcc一直win平台下产生的,所以是win版的gcc,既支持32也支持64bit 2cygwin专注于原样在windows上构建unix软件, 3msys让Linux开发者在windows上运行软件,msys2专注于构建针对windows api构建的本机软件 4 wsl  windows subsystem for linux 是一个在windows 10 上能