cookie与session

cookie与session是前端面试必问的问题。但是这两个理论都有点抽象,很多人往往无法很好的回答。因此必须结合实际的例子才好理解。
文章涉及一下内容:

  1. 为什么需要cookie
  2. 注册登录过程原理弄懂cookie
  3. 为什么需要session
  4. 手写前端获取对应cookie值的函数

为什么需要cookie?

  • Http是无状态协议,他不对之前发生过的请求和响应的状态进行管理。也就是说,http无法根据根据之前的状态进行本次的请求处理。(举个实际的例子,就像你和一个有健忘症的门房大叔谈话一样:你和他说,我是这个住这个小区的。他回你好。然后你说,开门让我进去。他又说你是谁,只有住这个小区的才可以进去。就是他无法记住你所过说的话。)
  • 所以需要引入cookie进行状态管理。还是上面那个例子:由于这个健忘的门房大叔,搞得小区一直被投诉。于是小区管理员决定,给每位居民颁发一个徽章,进门的时候只要给门房看这个徽章,他就让你进去。
  • Http响应通过
setHeader('Set-Cookie','cookieName=CookieValue;HttpOnly')

设置cookie.

  • 一般都要加上HttpOnly,这是为了防止前端操作cookie。因为一般来说,前端是不允许操作cookie的。因为如果前端能操作cookie,那么用户在浏览器的控制台也可以操作了。


    综上,可以这么总结cookie:
  1. cookie是浏览器下发给服务器的一段字符串
  2. 浏览器必须保存这个cookie(除非用户自己删除)
  3. 之后发起相同二级域名的请求(任何请求)时,浏览器必须附上cookie

结合注册与登录过程原理弄懂cookie

注册

这一步其实和cookie没什么关系,但是为了更好的理解,建议还是仔细看看

  1. 如果我第一次浏览一个网页,我必须注册账号
  2. 假如我的用户ID为:liu 密码为:123456。然后我点击注册按钮,其实就是往服务器发送了一个post请求,会把我所填的信息上传给服务器。
  3. 服务区读取我上传的数据:
//生成新数组
const array=[]
//监听request的data事件,把数据push到array里面
request.on('data', (chunk) => {
            array.push(chunk)
})
//监听request的end事件,数据上传完全后,用buffer.concat().toString()把数据转换成字符串
 request.on('end', () => {
            const string = Buffer.concat(array).toString()
})
  1. 服务器收到我上传的数据后,会把信息储存在本地的user.json文件里。
  2. 一般来说,密码是不会明文储存的。因为如果名文存储密码,如果服务器的user.json文件被窃取了,那么所有的用户信息就被窃取了,这就是常说的“脱库’”
  3. 所以为了安全起见,会在后端生成一个随机数random,然后把密码和random结合起来,再用sha256进行单向散射,生成一个值,然后再把生成的随机数和散射值存储在user.json,如一下格式;
{{"user_id":1,"name":"liu","random":1235,"secret":sha256(random+密码)},
 {"user_id":2,"name":"jack","random":5465,"secret":sha256(random+密码)}
}

登录

  1. 我输入注册过的用户名和密码,点击登录。实际上也是发送了一个Http的post请求,把输入的用户名和密码发送给服务器。
  2. 简单过一下服务器怎么处理我上传的数据
    首先会根据我提交的用户名,在user.json里面查找是否有匹配的用户。如果找到了,会从文件里面提取出所对应的random,然后加上我的密码,用sha256进行单向散射,所得的散射值与文件所储存的散射值对比,如果一致,即通过验证。
  3. 直到现在,cookie还是没有出现,接下来该它发挥作用了!
    一般来说,输入争取的用户名后,会跳转到home页面,每个user的home页面应该是不一样的(比如说,如果我是liu,那么我的home页面会显示“hello,liu”;如果我是jack,那么我的home页面会显示“hello,jack”)。但是游览器怎么知道我是哪个user呢??
  4. 对应的解决方法就是服务器给我(浏览器)发送一张身份证,那么以后我发起任何请求都会带上这张身份证,后台服务器会根据我的身份证号码不同,给我返回不同的响应。这个身份证就是cookie。
    看看服务器user.json存储的我的数据:
{"user_id":1,"name":"liu","random":1235,"secret":sha256(random+密码)},

那么服务器给我发送的cookie就是user_id=1
用node.js设置cookie:

response.setHeader("Set-Cookie","user_id=1;HttpOnly")



到这里,cookie的故事就算结束了。

为什么需要session?

session呢???session不是经常和cookie一起使用的吗?
没错,聪明的你肯定发现了上面这种设置cookie的方法存在巨大的安全隐患,就是user_id=1这种结构太简单了,我完全可以自己篡改!(虽然说加上HttpOnly可以防止用户操作cookie,但是有时候可能后端程序员不太小心忘记加上了,或者有时候确实需要前端来操作cookie不能加上)
我只要在浏览器控制台把我的cookie改为:user_id=2,那我不就等于登录了别人的帐号了吗?
为了防止篡改cookie情况的出现,session就登场了

  1. 服务器在后台新建一个x.json的文件。
  2. 服务器在发送cookie的时候,不会再发送user_id了(过于简单,容易被篡改),而是生成一个随机数random,作为session_id,然后把session_id和user_id存储在x文件里。(如果生成的随机数为0.23645456231231,我的user_id=1,那么会是这么储存:
{{0.23645456231231:{"user_d":1}}
  1. 之后,在发送cookie的时候,就会发送session_id,而不是user_id
response.setHeader('Set-Cookie',`session_id=${random};HttpOnly`)

由于session_id是随机的。而且很长,所以难以被篡改。

  1. 之后我发送请求时,我就会带上我的session_id。服务器收到我的请求后,会从session.json里面查找对应的session_id对应的user_id,然后再根据我的user_id在user.json文件里面查找我的信息,进而返回不同的响应。
  2. 因此有了session这一层的保护,cookie就会变得更加安全。


    一般来说回答到这里,cookie与session的基本原理就可以讲清了。但是还可以再为自己加分

手写前端获取对应cookie的值的函数

 function getCookie(cookieName) {
            const strCookie = document.cookie
            const arrayCookie = strCookie.split(';')
            let targetCookie
            try { targetCookie = arrayCookie.filter((cookie) => cookie.indexOf(cookieName + '=') >= 0)[0] }
            catch (error) { }
            if (targetCookie) {
                const cookieValue = targetCookie.split('=')[1]
                return cookieValue
            } else {
                return undefined
            }
        }



点击可参考注册与登录的服务器代码
clnoe后在命令行输入下面代码可运行。

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