session、token与jwt

图片发自简书App


session与cookie

什么是session

session翻译过来是会话,但在WEB领域常常是指会话数据:“同一客户端与服务端进行沟通时的上下文信息”,session的作用,我用一个例子来做比喻:

假设我在滴滴平台上叫车被司机拒载后,拨通了滴滴客服电话进行投诉,通话开始,我是客户端,滴滴客服则是服务端,我每一次讲话就是发送一个请求,她每一次回复则是响应

以下是一种可能的沟通情形:

我:你好,我在你们平台上叫了一个车被司机拒载,我现在想投诉他。客服MM:您好,给您带来不便非常抱歉,请问您的滴滴账号是多少?我:185xxxx8888。客服MM:您好,请问您要投诉哪一个行程订单?我:今天下午3点,从南山星巴克到北山星巴克,司机车牌尾号xxx。...

在我与滴滴客服的这次沟通中,session数据就是沟通过程中的信息上下文(滴滴账号、行程信息、司机车牌...),它的作用不言而喻,没有这些信息客服就不知道谁因为什么在投诉谁,所以session在这的作用是能帮助我完成这个投诉。

通过例子,我们能对session有一个简单理解,但对于HTTP应该如何记住session的内容却又是另外一回事,也许这个案例中客服接通我的电话时便撕出了一张便签纸,便签纸的页码是ignore-sb,随后过程中我与她沟通的信息她便记录在这张便签纸上。

在一对一的客服例子中,客服一直知道是与“我”在对话,但针对HTTP的情况是:“一个客服(服务端)同时处理成百上千的投诉(客户端)”,客服面临的挑战是在串线的情况下,将投诉过程中每一个有效信息记录到对应的便签纸上。由于串线,客服无法确定与她沟通的是哪个投诉用户,也就不能将用户发言中的有效信息记录到对应的便签纸上,在技术上这称为HTTP协议的无状态性:“没有来电显示的多路复用通讯”。

针对HTTP通信,如果同一个客户端先后发出两个请求,在服务端,如果不借用一些特殊手段是无法得知这两个请求来自同一个客户端,这就是HTTP协议的无状态性,它导致无法追踪会话,cookie的出现就是为了解决这个问题。

什么是cookie

cookie是HTTP协议中定义的一个请求头部字段,浏览器针对这个头部字段会有一些额外处理逻辑,如自动携带、跨域检查与过期删除等,与之对应的响应头部是set-cookie,用于服务器向客户端写入cookie数据。

session与cookie的关系

我们需要克服HTTP协议的无状态性,让服务端能够识别同一客户端,这样才能记录并利用session信息,针对上述例子,滴滴公司为此制订了一个投诉规则:

投诉用户如果知道自己的便签ID,则在每一次发言中必须先说:“我的便签是xxx”(cookie),然后再讲述内容,而客服则判断用户有没有讲出自己的便签ID,有则在已存在中寻找,无则从便签本中撕取,如果是撕取需要在回答的时候告知(set-cookie)用户这次撕取便签的ID,投诉用户会记住该ID并在后续的每次发言中优先说出:“我的便签是xxx”

如果大家严格遵守该规则,客服针对所有的用户发言都能够找到相应的便签并查看或更新便签上的信息,这样客服在串线情况下也能识别用户(假设串线不会打断用户的单次发言)。

在HTTP通信中,客户端请求在特定位置讲出服务端曾经给予自己的某些信息,浏览器的这个特定位置就是cookie,这是浏览器中最常见的做法。

cookie只是一个特定位置,但session并不依赖这个特定位置,条件允许的情况下我们可以更换成另外一个位置,从而我们知道session并不依赖cookie,如果激进一点,甚至可以说:“session与cookie没有关系”。

session也许可以脱离cookie存在,但cookie是为session而生,多年前网景公司为了解决HTTP无状态的问题而引进cookie这个HTTP头部,就是为了定义浏览器行业传输session的标准,现在所有的浏览器都支持cookie的一系列特性,如自动携带、跨域检查与过期删除等。不过随着HTTP应用场景的发展,现今很多HTTP场景也都不再受限于浏览器内,所以认识session与cookie的关系就很有必要,当处于在非浏览器环境下我们可以选择扩展HTTP头部等方式携带session信息。

cookie追踪session的技术实现

这一小节,我用Node.js实现了一个最简单的cookie/session的example。

session与cookie主要涉及两个HTTP头部:set-cookie与cookie,前者是一个响应头部,用来告知客户端需要记住的信息,后者是一个请求头部,用来告知服务端自己曾经记住的信息。

Talk is cheap show you the code:

// index.js

const http = require('http');

const _ = require('lodash');

const session = {};

const server = http.createServer((req, res) => {

let cookie = {};

// 从req.headers上获取cookie并解析为对象

_.each((req.headers.cookie || '').split(';'), item => {

let [name, value] = item.split('=');

cookie[name] = value;

});

// 通过cookie找到session数据,这里使用's'作为sessionId的在cookie中的名称

if (cookie.s) {

req.session = session[cookie.s] || {};

}

// 用户首次访问(没有sessionId或者session是空)

// 设置cookie并初始化session

if (!cookie.s || _.isEmpty(req.session)) {

req.session = {

firstVisit: Date.now()

};

let sessionId = Math.random().toString(16).substr(2);

session[sessionId] = req.session;

// 通过`set-cookie`向客户端设置cookie

// 此处没有考虑多个cookie情况

res.setHeader('set-cookie', `s=${sessionId}`);

}

res.end(`your first visit was ${req.session.firstVisit}.`);

});

server.listen(10000);

通过node index.js运行server,在浏览器中访问http://localhost:10000多次,每次显示的信息都是相同的,这就是因为根据cookie识别了同一用户,取到的session数据是相同的。

上面代码由于把session放在内存中,故不能支持水平扩展,进程重启也会导致所有session丢失,解决这两个问题的一般选择是将session数据存储在Redis中。

token

什么是token

token,翻译过来是令牌的意思,一般用于请求需要权限校验的接口,提供一个有效token就允许访问,否则拒绝访问。

token,正常是通过身份认证而获取的一个字符串凭证,这个凭证可用于在一定时间内请求一些权限需要才能获取的资源,其中最常见的认证方式是用户名+密码。

token相比每次认证的优点

因为认证的方式多种多样,进行身份验证后发放token作为授权,相比每次都进行身份验证显得更为灵活。比如手机号+验证码认证与证书认证所需成本相对较大,难以在每一个需要身份校验的地方都进行这种认证,所以使用token就显得非常有必要。另外,通过认证发放token的方式能相对减少原始认证要素被盗的几率,同时认证所发放的token一般具有有效期(越敏感有效期越短),也能降低被盗后的可能损失。

token与session及cookie的关系

token之所以会跟session与cookie扯上关系,需要从用户场景进行解释,一个web服务提供者面对的用户通常分为两种:游客与登录用户,对于游客我们一般不存储session,而登录用户至少需要记住其登录状态。对于如何记住用户登录状态,常见做法是在用户登录时,在其对应session中记录用户ID,而对于需要登录权限的操作,我们可以检查用户的session中是否存在用户ID,否则拒绝操作。

上述这种借助session识别用户是否登录的方式,客户端cookie中用于追踪session的那个值(sessionId)可被称为token,这个token通常是用户名+密码认证成功后所得到的。由此可见session与cookie跟token产生联系,是因为token的概念恰好有一个用session+cookie实现的场景。

token就是token,只是在特定场景利与session、cookie产生了联系,因此我们完全可以选择不借助session与cookie而使用token,比如在HTTP请求头中使用x-token头部传输token的值,又或者是在URL中携带token,这两者在如今都是较常见的做法。

jwt

什么是jwt

json形式的网站令牌,英文全称json web token,其实与token没多大区别,无非是使用json格式传输token罢了。

jwt跟session-token的区别

jwt是token的一种,但它与传统session-token的核心区别并不是因为jwt使用json格式,而是在使用方式上有所区别。前面讲到token与session及cookie的关系时,sessionId就是token,而sessionId对应的session数据保存在服务器端,一般需要持久化才能满足应用水平扩展需要。

当用户量足够大的时候,考虑到session数据的存储是单点,可能遭遇瓶颈,于是jwt出现了,它的最大优势就是可以消灭session存储这个单点。jwt的具体做法并不复杂,只是把之前存储在服务端的session数据用json格式转移到客户端存储,同时为了不被破解和窜改会使用加密和签名两个手段。

上述描述过程中我将session与jwt所携带的数据等同了,严格意义上他们并不等同,因为jwt携带的数据更多的是关注与授权验证有关的,而所有与会话相关的数据都可以称为session,比如我认为cookie中的所有数据都可以算是session的一部分。

总结

综合前文,这里再对token、jwt、session、cookie做一个简述:

token是一个独立的概念,是通过认证后发放的某个“凭证”,这个凭证可以通过cookie、自定义http头部,URL的query进行传递

jwt是token的子集,采用json格式以及附带一些规范约束

session,常常用来表示会话数据,笼统点讲就是所有跟会话有关系的数据,具体点就是服务端为会话所存储的数据

cookie,浏览器下最方便传递session数据的方式

彩蛋

图片发自简书App


过了几天,在app内看到滴滴的投诉处理完成了,故打电话向客服询问处理结果:

我:你好,我在app内看到上次的投诉处理完成了,请问处理结果是啥?客服MM:您好,您的投诉我们相关部门已经处理,但是处理结果不对外公布。我:处理结果不对外公布,那我如何知道你们已经处理?客服MM:先生,您的投诉我们相关部门已经处理,但是无法告知您。我:...客服MM:先生,处理结果是我们相关部门已经处理。我:...客服MM:先生,您好,我们公司规定处理结果不对外公布。我:...客服MM:先生,真的非常抱歉,我们已经处理,但是处理结果不对外公布。...

这是一个真实的故事,派单给司机时离我大概600米,可能不想跑了就打电话找借口让我取消,我没有答应,随后,司机把车从我眼前开走并在APP内操作已到达,5分钟后算我超时被取消,气炸了后投诉司机,最终也没能知道有没有处理以及怎么处理,这种投诉结果不对外公布是谁TM想出来的?

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,839评论 6 482
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,543评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 153,116评论 0 344
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,371评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,384评论 5 374
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,111评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,416评论 3 400
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,053评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,558评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,007评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,117评论 1 334
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,756评论 4 324
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,324评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,315评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,539评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,578评论 2 355
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,877评论 2 345

推荐阅读更多精彩内容