案例分析cookie和session

本篇文章主要总结了 cookie session的原理,以及会话控制。下面是使用简单的代码来解析,还是比较容易懂的,还可能存在不足,欢迎各位大佬☞正

想要了解cookie,首先需要了解http是什么。好了,下面就从http的原理开始说吧

HTTP的诞生:

CERN(欧洲核子研究组织)的蒂姆 • 伯纳斯 - 李(Tim BernersLee) 博士提出了一种能让远隔两地的研究者们共享知识的设想。

最初设想的基本理念是:借助多文档之间相互关联形成的超文本 (HyperText),连成可相互参阅的 WWW(World Wide Web,万维 网)。

现在已提出了 3 项 WWW 构建技术,分别是:把 SGML(Standard Generalized Markup Language,标准通用标记语言)作为页面的文本标 记语言的 HTML(HyperText Markup Language,超文本标记语言); 作为文档传递协议的 HTTP ;指定文档所在地址的 URL(UniformResource Locator,统一资源定位符)。

如果你想要更深入了解http,那么需要了解他的底层Tcp,可以参考电子书图解HTTP

HTTP 是不保存状态的协议

HTTP 是一种不保存状态,即无状态(stateless)协议。HTTP 协议自 身不对请求和响应之间的通信状态进行保存。也就是说在 HTTP 这个 级别,协议对于发送过的请求或响应都不做持久化处理。

那么这个无状态中的“状态”,是什么呢:可以简单这样理解:就是信息,这些信息是由服务端所维护的与客户端交互的信息(也称为状态信息),因为HTTP本身是不保存任何用户的状态信息的,所以HTTP是无状态的协议。

cookie的诞生:

HTTP 协议自身不具备保存之前发送过的请求或响应的功能 ,也就是Http本身是无状态的,使用 HTTP 协议,每当有新的请求发送时,就会有对应的新响应产生。协议本身并不保留之前一切的请求或响应报文的信息。这是为了 更快地处理大量事务,确保协议的可伸缩性,自然可减少服务器的 CPU 及内存资源的消耗。(简单来说,浏览一写静态的文件和文档,已经足够使用了)

图示:服务器管理全部客户端状态则会成为负担

这时候我们考虑一个问题,假设要求登录认证的 Web 页面本身无法进行状态的管理(不记录已 登录的状态),那么每次跳转新页面不是要再次登录,就是要在每次 请求报文中附加参数来管理登录状态。

这个时候。很多业务网站都需要状态信息得以保存;但是,一方面是http本身不会去改变它的这种无状态的特性,所以这个时候需要引入一些机制来装饰下HTTP,让HTTP达到可以保存客户端和服务端之间通信的状态。

cookie和session的引入:

通过引入cookie和session体系机制来维护状态信息,Cookie 技术通过在请求和响应报文中写入 Cookie 信 息来控制客户端的状态。Cookie 会根据从服务器端发送的响应报文内的一个叫做 Set-Cookie 的 首部字段信息,通知客户端保存 Cookie。当下次客户端再往该服务器 发送请求时,客户端会自动在HTTP请求报文中加入 Cookie 值后发送出 去。cookie中存有sessionId这样的信息(session是基于cookie的),来到服务器这边对比服务器上的记录。最后得到之前 的状态信息。

Cookie技术原理:

Cookie 的工作机制是用户识别及状态管理,Cookie 技术通过在请求和响应报文中写入 Cookie 信 息来控制客户端的状态。由服务器发送给客户端(浏览器)的小量信息,以{key:value}的形式存在。Cookie 会根据从服务器端发送的响应报文内的一个叫做 Set-Cookie 的 首部字段信息,通知客户端保存 Cookie。当下次客户端再往该服务器 发送请求时,客户端会自动在HTTP请求报文中加入 Cookie 值后发送出 去,来到服务器这边对比服务器上的记录。最后得到之前 的状态信息。

Cookie的属性:

Cookie 服务的首部字段

1. Set-Cookie字段的属性

expires 属性

Cookie 的 expires 属性指定浏览器可发送 Cookie 的有效期。 当省略 expires 属性时,其有效期仅限于维持浏览器会话(Session) 时间段内。这通常限于浏览器应用程序被关闭之前。

path 属性

Cookie 的 path 属性可用于限制指定 Cookie 的发送范围的文件目录。 不过另有办法可避开这项限制,看来对其作为安全机制的效果不能抱 有期待。

domain 属性

通过 Cookie 的 domain 属性指定的域名可做到与结尾匹配一致。比 如,当指定 example.com 后,除 example.com 以外,www.example.com 或 www2.example.com 等都可以发送 Cookie。

secure 属性

Cookie 的 secure 属性用于限制 Web 页面仅在 HTTPS 安全连接时,才 可以发送 Cookie。发送 Cookie 时,指定 secure 属性的方法如下所示。

Set-Cookie: name=value; secur

HttpOnly 属性

Cookie 的 HttpOnly 属性是 Cookie 的扩展功能,它使 JavaScript 脚本 无法获得 Cookie。其主要目的为防止跨站脚本攻击(Cross-site scripting,XSS)对 Cookie 的信息窃取。

HttpOnly=true 

通过上述设置,通常从 Web 页面内还可以对 Cookie 进行读取操作。但使用 JavaScript 的 document.cookie 就无法读取附加 HttpOnly 属性后 的 Cookie 的内容了。因此,也就无法在 XSS 中利用 JavaScript 劫持 Cookie 了。

2.Cookie

Cookie: status=enable

首部字段 Cookie 会告知服务器,当客户端想获得 HTTP 状态管理支 持时,就会在请求中包含从服务器接收到的 Cookie。接收到多个 Cookie 时,同样可以以多个 Cookie 形式发送。

Cookie小案例:记录访问浏览器的数次

此时httponly也不太安全,它可以手动操作改动,所以下面可以加入签名来实现加密。

就比如jd.com里面的cookie类似,你根本看不懂是一串看不懂的数字,但是你不知道它代表什么含义?

浏览器可以修改cookie -----> 签名

此时改变cookie的值,已经毫无意义了,改变之后,发送到服务器对比之后,发现状态不一样,会重新请求。


const http = require("http");
const querystring = require("querystring");
const sign = (value) => {
    return require("crypto").createHmac("sha256", "abc").update(value).digest("base64").replace(/\+/g, "")
}
http.createServer((req, res) => {
    let arr = [];
    res.setCookie = function (key, value, options = {}) {
        let opts = [];
        if (options.domain) {
            opts.push(`domain=${options.domain}`)
        }
        if (options.maxAge) {
            opts.push(`max-age=${options.maxAge}`)
        }
        if (options.httpOnly) {
            opts.push(`httpOnly=${options.httpOnly}`)
        }
        if (options.signed) {
            value = value + '.' + sign(value)
        }
        arr.push(`${key}=${value}; ${opts.join("; ")}`)
        res.setHeader('Set-Cookie', arr);
    }
    req.getCookie = function (key,options = {}) {
        let obj = querystring.parse(req.headers.cookie, "; ");
        if (options.signed) {
            if (obj[key]) {
                let [value, s] = obj[key].split('.')
                console.log(value)
                let newSign = sign(value);
                // console.log(s,newSign)
                if (s === newSign) {
                    return value
                } else {
                    return undefined;
                }
            }
        }
        return obj[key];
    }
    if (req.url === "/write") {
        // res.setCookie("name","wangcai");  
        // res.setCookie("age","100");  
        res.end("write ok ~")
        return
    }
    if (req.url === "/read") {
        res.end(req.getCookie("age") || 'empty');
    }
    if (req.url === "/visit") {
        res.setHeader("Content-type", "text/plain; charset=utf8")
        let visit = req.getCookie("visit",{signed:true});
        if (visit) {
            visit = visit - 0 + 1;
            res.setCookie("visit", visit + "", { httpOnly: true ,signed:true})
        } else {
            visit = 1;
            res.setCookie("visit", "1", { httpOnly: true ,signed:true})
        }
        res.end(`当前第${visit}次访问`)
    }
}).listen(3000);

Session技术:

Cookie机制弥补了HTTP协议无状态的不足。在Session出现之前,基本上所有的网站都采用Cookie来跟踪会话。

与Cookie不同的是,session是以服务端保存状态的。

Session技术原理:

session是基于cookie 第1次请求时,服务器会把一个session_id以cookie形式种植给浏览器。以后客户端在访问服务端时候,http会带着session_id,服务器会先检查这个客户端的请求里是否已包含了一个session标识----sessionId。如果已包含这个sessionId,则说明以前已经为此客户端创建过session,服务器就按照sessionId把这个session检索出来使用。

session小案例:

将session类比与一张饭卡,起初500元,每次刷新减少100

const http = require("http");
const querystring = require("querystring");
let uuid = require("uuid")
let cardName = "tian"
// 先把session存储到内存中    后面我们会把session数据存储到数据库
let session = {};
http.createServer((req,res)=>{
    let arr = [];
    res.setCookie = function(key,value,options={}){
        let opts = [];
        if(options.domain){
            opts.push(`domain=${options.domain}`)
        }
        if(options.maxAge){
            opts.push(`max-age=${options.maxAge}`)
        }
        if(options.httpOnly){
            opts.push(`httpOnly=${options.httpOnly}`)
        }
        arr.push(`${key}=${value}; ${opts.join("; ")}`)
        res.setHeader('Set-Cookie', arr);
    }
    req.getCookie = function(key,options = {}){
        let obj = querystring.parse(req.headers.cookie,"; ");
        return obj[key];
    }
    if(req.url === "/eat"){
        let id = req.getCookie(cardName);
        if(id){  // 有卡  
            // session[id].mny = session[id].mny - 100
            session[id].mny -= 100
            res.end("current money is $"+session[id].mny)
        }else{
            let cartId = uuid.v4();
            // console.log(cartId) // c1cddd32-e6f7-40fa-9fed-b711489a4bf9
            session[cartId] = {mny:500}
            res.setCookie(cardName,cartId)
            res.end("current money is $500")
        }
        res.end("eat...")
    }
}).listen(3000);

一个常见且重要的面试题:

localStorage, sessionStorage, cookie, session有什么区别?
localStorage 不能跨域存取 最大存5M 超过5M的数据就会丢失 在发送请求时,不会带上 存储数据永久存储
sessionStorage 当浏览器关闭时,里面的数据就丢失
cookie 服务器种植的,每次请求都会带上cookie,安全,解决无状态问题,最多4K,浪费流量
session 基于cookie 保存在服务器(内存,入库) 相对安全

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值