千帆云

 找回密码
 立即注册

QQ登录

只需一步,快速开始

查看: 1126|回复: 0
打印 上一主题 下一主题

会话机制之cookie&session VS JWT

[复制链接]

7

主题

11

帖子

0

积分

超级版主

Rank: 8Rank: 8

积分
0
跳转到指定楼层
楼主
发表于 2019-3-7 11:31:08 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式 | 来自江苏
本帖最后由 千帆开发陈余邹 于 2019-3-15 17:59 编辑


HTTP协议  超文本传输协议(HTTP)  核心点:文本  无状态

请求头

GET / HTTP/1.1
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.121 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: UM_distinctid=165ac7ed3414db-08511170d12141-34627908-1fa400-165ac7ed3431001; CNZZDATA1261519046=1752608278-1520836563-%7C1551698473
Connection: keep-alive

POST /admin/index/login/ HTTP/1.1
Host: qianfan1.adm.qianfanyun.com
Content-Length: 32
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
Content-Type: application/x-www-form-urlencoded
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.121 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: remember=0; _admin=5feaddb0cb2ff72f19629d8cc26b955a095f7bdba%3A4%3A%7Bi%3A0%3Bs%3A1%3A%221%22%3Bi%3A1%3Bs%3A5%3A%22admin%22%3Bi%3A2%3Bi%3A86400%3Bi%3A3%3Ba%3A2%3A%7Bs%3A4%3A%22name%22%3Bs%3A5%3A%22admin%22%3Bs%3A6%3A%22access%22%3Bi%3A100%3B%7D%7D; UM_distinctid=169562f34c415a-0e09e47665d8e8-36667902-1fa400-169562f34c574b; PHPSESSID=j7s9gr95lmrvs1gf9uo7i4vgve
Connection: keep-alive

username=admin&password=12345678

响应头

HTTP/1.1 200 OK
Server: Tengine
Content-Type: text/html; charset=UTF-8
Transfer-Encoding: chunked
Date: Wed, 06 Mar 2019 08:55:29 GMT
Vary: Accept-Encoding
X-Powered-By: PHP/5.6.7
Set-Cookie: PHPSESSID=ln3e5vq2689fd1lechp57g3h30; path=/; HttpOnly
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Pragma: no-cache
Ali-Swift-Global-Savetime: 1551862529
Via: cache1.l2et2[58,200-0,M], cache32.l2et2[61,0], cache9.cn932[87,200-0,M], cache8.cn932[88,0]
X-Cache: MISS TCP_MISS dirn:-2:-2
X-Swift-SaveTime: Wed, 06 Mar 2019 08:55:29 GMT
X-Swift-CacheTime: 0
Timing-Allow-Origin: *
EagleId: b461f59c15518625297797428e
Proxy-Connection: keep-alive

<!DOCTYPE html>
…(响应体)

HTTP协议也是协议,就是文本+控制符:主要是\n\n划分header和body   header各行用\n   键值用:隔开

Cookie
然后来看会话保持怎么做,首先我们能想到的是在HTTP来回传输过程中,带有一些记号,就可以实现了。怎么做?我们可以放在GET中(也就是跟在url后面),可以放在POST里面,当然也也可以放在请求头Header里面,Cookie其实也是Header的一部分。

我们举一个书店老板的例子来说明一下:
首先不需要会话保持,书店也能开起来。书店老板(Server端)提供借书服务,书客(Client端)来借书。
比如hao123这样导航网站,各种咨询网站,看就完了。
有一天书店老板的业务需要进一步发展,他想弄一个会员系统,借书一次可以累计积分,给予优惠。这时候就需要一种会话保持的技术。也就是过来一个书客,老板需要识别出这个是新用户,还是老用户。回到上面说的怎么做会话保持,就是书客过来借书的时候给一些记号(会员卡),老板记下来就行了。
这个记号放在哪里其实都是可以的,比如你把会员卡贴在脸上,或者挂在胸口,正常都是揣在口袋里,到了书店给老板就行(只需要server/client协商好即可)。
在网络世界里面,映射到HTTP协议里面,这个会员卡是怎么样的?就类似于一张白纸,上面写了"UID=1"这样一串符号。这就是cookie的原型。
为什么
注意:cookie不仅仅可以跟在header头部在网络间传输,客户端还需要做本地存储,当收到老板发的会员卡,我得存下来。为什么不用GET/POST/Header,因为没有本地存储,关掉浏览器,再打开首页的时候标记就没了。所以cookie存起来,每次请求网站的时候都带着本地的cookie去请求,Server端就有办法识别是谁了。

于是cookies就被设计出来了,主要就是存一些保持状态的信息的,但是cookie不是简单的字符串,而是一个对象,有键、值、过期时间、作用域和路径。核心属性还是键值。我们看一下浏览器里面的cookie,还有几个字段  httpOnly,Secure,SameSite 作用。

Session
这样有什么问题:太容易伪造了。我第一次去借书,老板给我一张会员卡id=100,那我是不是可以把100改成1再去找老板借书试试?如果是电商系统,这个就很严重了。所以这种就用Cookie存会员信息的方案显然是不太可行的。(人类可以通过大脑的记录来给会员卡(用户的样子)做鉴别,在HTTP协议里面就无法鉴伪,大家都是文本。而且就算是人也会偶尔有失误

上述方案的核心问题是,把uid=1这样容易猜测的内容写到会员卡,很容易被猜出来。
那我就在会员卡上写f19629d8cc26b955a095f7bdb这样一串不容易猜的标记,再把这一串标记记到书店的会员账簿中。
f19629d8cc26b955a095f7bdb ->  uid=100
s0d1vgrsia99u710kf7b9n87l3 ->   uid=101

这样就不容易伪造了,(理论上还是还是可以通过无限尝试去猜到其他用户的会员码的,只要我们给出的会员码越没有规律,就越不容易被猜到,而且加上过期时间就更安全了)

这个老板店里的会员账簿  就是我们的session。

使用cookie和session结合,就实现了状态保持。
看一下我们的千帆云网站   
Set-Cookie: PHPSESSID=s0d1vgrsia99u710kf7b9n87l3; path=/; HttpOnly
JAVA里面  JSESSIONID
PHPSESSID后面的值就就是上面说的乱码,当我开启了session,每个过来访问的用户我都生成这样一段乱码存进cookie,然后记录在我们的服务器client账簿中,下次这个client再来请求的时候 带着这段乱码过来,server根据这个断码查一下账簿,就知道这是刚才那个client了,
这些php都已经帮我们做好了,我们写php代码的时候  打开session会话,直接$_SESSION就行了。

session怎么存储
这个账簿长什么样子呢,其实只要是可以记录东西的地方都可以,可以是文件、memcache、redis、甚至db中,只要是存储系统就行。

redis、memecache、mysql、文件存储各有什么优势呢?跟这几种存储方式的特性也有关系,
比如mysql速度相对比较慢,每一次请求都要查mysql,而mysql又是我们当前网站系统里面最容易成为瓶颈的地方,所有在后台系统里可以用,前台并发量不大的时候也可以用,并发高了就不划算了,(主要还需要定期删除已经过期的session记录,不然mysql越来越大严重影响性能,当天并不是每次查询的时候都执行delete,可以有一个策略,比如1%的概率触发删除操作)
redis、memache都差不多,也是我们当前主要采取的存储策略,内存操作,速度快,设置的时候就弄好过期时间,清理就不用操心了,但是也有问题,比如memcache当内存快慢的时候会采用LRU算法将部分数据删除,万一正好删掉了你的session,就会出现你登录之后,下单之后点付款,提示你尚未登录。
在你如memcache重启  当前登录用户的状态全丢,redis启用持久化就没有这个问题。
文件存储,一样,是io操作,每次访问 都有io操作的话,并发够的时候也会影响到服务器的整体负载。


上面这些都是php做好了的 ,我们只需要在php.ini里面配置即可。默认是文件存储。也可以改成redis/memcache。
当然在我们的yii2中,也对session进行了封装,我们也可以在yii2的组件中配置session存储策略。yii2里面是可以设置为mysql的。


JWT
cookie和session就介绍完了。下面介绍现在的一种保持会话的技术,jwt。
我们回顾一下上面的Session产生的原因,就是解决安全性的问题。如果有一种办法,只要通过会员卡就可以鉴别用户的真伪,是不是就可以了?
会员卡技术,在会员卡上做一些防伪标记,用户来借书,我就鉴别一下会员卡的真伪就行。服务器也不需要存会员信息了。这个就设计到加密算法。
JWT就是这样一种实现。


jwt  VS cookie&session
其实jwt就类似最开始的纯cookie方案,但是做了升级,解决了安全问题。
session访问,需要服务器端存储session,每次访问都需要访问session,文件有io操作,memcache、redis内存操作,还存在丢失的可能性。数据库更不靠谱。session要基于cookie,cookie可能被禁止(现在我们解释一下为什么session要依赖cookie。因为书店里面的账簿上记录的就是会员卡上面的信息。会员卡没了,账簿上的信息也就没有意义了)

jwt 增加了服务器的cpu开销,因为要cpu去算真伪的。而我们现在的服务器 一般来说cpu都不会是瓶颈,所以这种方式最近比较流行。

vip会员卡:
uid:1
Username:xxx
...(其他信息,根据业务需求)
signire:签名信息  签名信息是哪来的,就是把上面的所以信息按照一定的规则放到一起,然后使用密文进行加密,得到密文,再对密文进行摘要,得到摘要(签名其实就是摘要)
网上看的时候注意几个术语    摘要算法≈哈希算法    信息指纹=消息摘要=哈希摘要=哈希值=散列值

原内容   摘要算法 得到 摘要(固定长度)
原内容   机密算法 得到 密文

MD5即Message-DigestAlgorithm 5(信息-摘要算法5)
https://www.cnblogs.com/geekdc/p/8979736.html

session和jwt的一些简单对比
因为认证是一种非常普遍的需求,session是集成在php里面的,jwt就需要自己去实现(有现成的库可以调用)
Jwt的存储,可以存cookie,也可以存storage。
cookie   既可以本地存储,也可以跟着http来回传输。 用cookie一下就解决了存储和传输的问题,还可以利用cookie的过期时间,不需要自己处理过期时间了。
stroage  只是存储,但是不能跟着http来回传输,所以如果用stroage来存的话,我们需要手动处理请求,每次请求都把jwt信息放到header头里面带给服务器。而且要自己处理过期时间等问题。
那为什么推荐stroage呢?  可能是应为cookie不安全,或者可能会被禁用(jwt还是一种可替代cookie的方案,不仅仅是有保持会话的功能)。cookie会被xss攻击被窃取。(通过某种手段拿到了人家的会员卡,那你直接就可以去借书了,而且能通过书店老板的检查。没必要自己去伪造身份信息了)
其实这两种方案都行,现在我感觉cookie的方案更加合理(cookie可以使用的情况下)

现在流行的区块链技术  最底层原理 其实就是这里说的加密、摘要算法。如果想做区块链开发,这个是必须掌握的知识。
我们现在的https证书,也是对这种技术的综合使用。后期会员专门的培训来讲这个。

自己实现用户机制
我们自己的实现机制  实际上是类似的,只不过jwt是一种通用的Oauth2方案,
我们自己目前在wap端的方案:把用户信息写进cookie,然后对cookie进行加密(注意是加密,密文包含了所有的信息,知道加密方法可以解出原文)


最后简单介绍一下加密技术
加密  就是一个内容放到盒子里面,外面加个锁,你有钥匙解开就能拿到里面的内容。
摘要  就是提取特征码,同一个内容必然提取出相同的特征码,提取出来的特征码也必须是源内容的独一无二的特征,根据特征就能识别出来是你。比如就是弄个指纹(面部识别也算,更复杂些而已,没有指纹简单),把指纹记录起来,不同的人有不同的指纹,我弄一个指纹库,根据你的指纹就能知道是你,(MD5其实就是摘要算法)。指纹本身并不包含你这个人的全部信息。MD5也是的,我们可以对一串很短的字符串摘要,也可以对一个很大的文件进行摘要,摘要出来固定就是32位字符串,其实就类似按个指纹,提取了你的特征(注意有一点很重要,就是每个人的指纹都不同,不同原内容MD5出来的摘要内容也不相同,相同的原内容MD5出来的摘要肯定相同,这是一个很重要的特点,当然目前好像也有说发现两个不通的内容可以MD5出相同的摘要信息,这就是所谓的碰撞。)
怎么理解  摘要就是提取特征码   比如李奕飞、李平 我们给他们起个外号 飞哥、平儿、这两个代号就能指代他们俩。我们通过简单的摘要算法给李奕飞计算摘要就是飞哥,李平=》平儿。飞哥就能指代李奕飞。平儿就可以指代李平。只是你的一个特征。但是这个特征必须是确定的,唯一的,没有歧义的。
比如摘要出来的两个人都叫小李,那就有歧义,不能唯一指代是谁。这个摘要算法就是无效算法。当然这个例子不是非常恰当。
摘要算法核心点:一样的原内容必定摘要出相同的哈希值(特征值),不同的原内容摘要出来的结果肯定不同,哪怕两个几G的内容值相差一个字母,摘要出来的结果都千差万别。

常见的摘要还有SHA-1摘要,他们的实现不同,原理一样,对我们应用来可以说没啥区别,就是不同的摘要方式而已。
针对摘要的破解是彩虹表  就是比对,也是根据相同原内容MD5出来的摘要肯定相同这个特点。并不存在破解算法

加密不一样,一般加密的密文里面是包含着所以原文信息内容的,只要知道解密算法,可以解出原内容的。

为什么我们村密码都用md5呢,其实我们本身就不需要存原密码,利用摘要的特性,只要知道用户提交的密码是对的就行了。所以只需要存摘要,不需要存密文。密文存在被破解的可能。摘要本身不包含密文内容,所以安全的多。当然如果只是简单的md5摘要,现在也不算安全了,一般还会进行加盐。增加被包里破解的难度。

常用的加密算法  大体分为对称加密 和非对称加密。

base64编码(编码算法),我们可以暂且认为这是加密算法。首先肯定不是摘要算法,严格来说,这也不是加密算法。因为加密是需要带秘钥去加密的,解密也需要秘钥,base64无需秘钥既可以加解密。

而在现实用,我们经常是综合摘要和加密一起来使用的。

摘要:速度快,不管是大文件还是小文件,速度都很可观。
加密:速度慢,特别是大文件,几个G的加个密,根据算法不同,往往需要很久很久,
。。。


cookie:   书店的会员卡
session:  书店记录会员卡信息的账簿
jwt:    带了签名的会员卡(会员卡升级版)


关键词:
会话保持:session机制,jwt、加密&摘要、对称加密&非对称加密

关联阅读:

理解是最重要的,理解之后结合一些网文和自己的实践去彻底消化吸收。

《大型分布式网站架构的设计和实现》陈康贤著里面有专门介绍加密的部分。公司的书










分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 支持支持 反对反对
呵呵
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|Archiver|手机版|小黑屋|千帆移动开放平台  

GMT+8, 2024-5-21 04:22

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表