当前位置: 首页 > news >正文

[网络]HTTP协议 Cookie与Session

一、Cookie

1.1 定义

HTTP Cookie(也称为 Web Cookie、浏览器 Cookie 或简称 Cookie)是服务器发送到 用户浏览器并保存在浏览器上的一小块数据,它会在浏览器之后向同一服务器再次发 起请求时被携带并发送到服务器上。通常,它用于告知服务端两个请求是否来自同一浏览器,如保持用户的登录状态、记录用户偏好等。

1.2 工作原理

  • 当用户第一次访问网站时,服务器会在响应的 HTTP 头中设置 Set-Cookie 字段,用于发送 Cookie 到用户的浏览器。
  • 浏览器在接收到 Cookie 后,会将其保存在本地(通常是按照域名进行存储)。
  • 在之后的请求中,浏览器会自动在 HTTP 请求头中携带 Cookie 字段,将之前保存的 Cookie 信息发送给服务器。

Cookie一般分为两种,一个是内存级的Cookie,只要关闭浏览器Cookie就会自动销毁,另一个是文件级的Cookie,即关闭浏览器Cookie仍然有效

  • 会话 Cookie(Session Cookie):在浏览器关闭时失效。
  • 持久 Cookie(Persistent Cookie):带有明确的过期日期或持续时间, 可以跨多个浏览器会话存在。
  • 如果 cookie 是一个持久性的 cookie,那么它其实就是浏览器相关的,特 定目录下的一个文件。但直接查看这些文件可能会看到乱码或无法读取的内容, 因为 cookie 文件通常以二进制或 sqlite 格式存储。一般我们查看,直接在浏览器对应的选项中直接查看即可。

1.3 认识Cookie

  • HTTP 存在一个报头选项:Set-Cookie, 可以用来进行给浏览器设置 Cookie 值。
  • 在 HTTP 响应头中添加,客户端(如浏览器)获取并自行设置并保存 Cookie。
1.3.1基本格式
//简单示例
Set-Cookie: <name>=<value>
其中 <name> 是 Cookie 的名称,<value> 是 Cookie 的值。//完整示例
Set-Cookie: username=peter; expires=Thu, 18 Dec 2024 12:00:00
UTC; path=/; domain=.example.com; secure; HttpOnly

时间格式必须遵守 RFC 1123 标准,具体格式样例:

Tue, 01 Jan 2030 12:34:56 GMT 或者 UTC(推荐)

GMT和UTC的区别

1. 计算方式:GMT 基于地球的自转和公转,而 UTC 基于原子钟。

2. 准确度:由于 UTC 基于原子钟,它比基于地球自转的 GMT 更加精确。 在实际使用中,GMT 和 UTC 之间的差别通常很小,大多数情况下可以互换使用。但 在需要高精度时间计量的场合,如科学研究、网络通信等,UTC 是更为准确的选择。

关于其他可选属性的解释

  • expires=[要验证]:设置 Cookie 的过期日期/时间。如果未指定此属 性,则 Cookie 默认为会话 Cookie,即当浏览器关闭时过期。
  • path=[要验证]:限制 Cookie 发送到服务器的哪些路径。默认 为设置它的路径。
  • domain=[了解即可]:指定哪些主机可以接受该 Cookie。默 认为设置它的主机。
  • secure[了解即可]:仅当使用 HTTPS 协议时才发送 Cookie。这有助于防止 Cookie 在不安全的 HTTP 连接中被截获。
  • HttpOnly[了解即可]:标记 Cookie 为 HttpOnly,意味着该 Cookie 不能被客户端脚本(如 JavaScript)访问。这有助于防止跨站脚本攻击(XSS)。

注意事项

  • 每个 Cookie 属性都以分号(;)和空格( )分隔。
  • 名称和值之间使用等号(=)分隔。
  • 如果 Cookie 的名称或值包含特殊字符(如空格、分号、逗号等),则需要 进行 URL 编码。
  • 如果设置了 expires 属性,则 Cookie 将在指定的日期/时间后过期。
  • 如果没有设置 expires 属性,则 Cookie 默认为会话 Cookie,即当浏览器关闭时过期。
1.3.2 测试浏览器自动写入Cookie

当我们第一次使用浏览器访问服务器时,浏览器会将Cookie信息自动保存起来,当我们再次访问,浏览器会将保存的Cookie信息添加到请求报头中返回给服务器,服务器接收到请求后,会解析HTTP请求头中的cookie字段,根据Cookie中的信息(如用户ID、会话ID等),服务器可以识别出用户的身份和状态,从而提供相应的服务。

class HttpServer
{
public:std::string GetWeekDayName(int day){std::vector<std::string> Week = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};return Week[day];}std::string GetMonthName(int month){std::vector<std::string> Months = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};return Months[month];}std::string ExpireTimeUseRfc1123(int t){time_t timeout = time(nullptr) + t; // 获取未来t秒的时间戳struct tm *tm = gmtime(&timeout);char timebuffer[1024];// 时间格式如: expires=Thu, 18 Dec 2024 12:00:00 UTCsnprintf(timebuffer, sizeof(timebuffer), "%s, %02d %s %d %02d:%02d:%02d UTC",GetWeekDayName(tm->tm_wday).c_str(),tm->tm_mday,GetMonthName(tm->tm_mon).c_str(),tm->tm_year+1900,tm->tm_hour,tm->tm_min,tm->tm_sec);return timebuffer;}std::string HandlerHttpRequest(std::string &reqstr){std::cout << "---------------------------------------" << std::endl;std::cout << reqstr;std::cout << "---------------------------------------" << std::endl;HttpRequest req;req.DeSerialize(reqstr);HttpResponse resp;resp.AddCode(200, _code_to_desc[200]);//测试Cookie自动被写入resp.AddHeader("Set-Cookie","username=zhangsan;");resp.AddBodyText("<html><h1>helloworld</h1></html>");std::string respstr = resp.Serialize();return respstr;}private:std::unordered_map<std::string, std::string> _mine_type;std::unordered_map<int, std::string> _code_to_desc;std::unordered_map<std::string, func_t> _service_list;
};

1.3.3 测试写入Cookie过期时间
    std::string HandlerHttpRequest(std::string &reqstr){std::cout << "---------------------------------------" << std::endl;std::cout << reqstr;std::cout << "---------------------------------------" << std::endl;HttpRequest req;req.DeSerialize(reqstr);HttpResponse resp;resp.AddCode(200, _code_to_desc[200]);// 测试写入Cookie过期时间//设置Cookie在30秒后过期resp.AddHeader("Set-Cookie", "username=zhangsan; expires="+ExpireTimeUseRfc1123(30)+";");  resp.AddBodyText("<html><h1>helloworld</h1></html>");std::string respstr = resp.Serialize();return respstr;}

1.3.4 测试路径path

我们将Cookie的可用路径设置为 /a/b ,则当浏览器第一次访问服务器时浏览器会自动保存Cookie,在之后的访问中,只有我们访问的路径设置为/a/b,浏览器才会将Cookie信息返回给服务器

   std::string HandlerHttpRequest(std::string &reqstr){std::cout << "---------------------------------------" << std::endl;std::cout << reqstr;std::cout << "---------------------------------------" << std::endl;HttpRequest req;req.DeSerialize(reqstr);HttpResponse resp;resp.AddCode(200, _code_to_desc[200]);//测试路径pathresp.AddHeader("Set-Cookie","username=zhangsan; path=/a/b");resp.AddBodyText("<html><h1>helloworld</h1></html>");std::string respstr = resp.Serialize();return respstr;}

单独使用Cookie的安全问题

        现在浏览器保存的是我们的测试数据,如果写入的数据是用户的私密数据,例如用户名密码的等,由于Cookie是保存在客户端的,那这些数据就有可能被别人非法获取,造成用户的私密信息泄露,那如何才能解决这个问题呢?于是就引入了Session

二、Session

2.1 定义

HTTP Session 是服务器用来跟踪用户与服务器交互期间用户状态的机制。由于 HTTP 协议是无状态的(每个请求都是独立的),因此服务器需要通过 Session 来记住用户的信息。

2.2 工作原理

1. 当用户首次访问网站时,服务器会为用户创建一个唯一的 Session ID,并通过 Cookie 将其发送到客户端。

2. 客户端在之后的请求中会携带这个 Session ID,服务器通过 Session ID 来识 别用户,从而获取用户的会话信息。

3. 服务器通常会将 Session 信息存储在内存、数据库或缓存中。

2.3 安全性

单独使用cookie不安全的原因是将用户的隐私信息直接保存在了客户端,容易被盗取,与 Cookie 相似,由于 Session ID 是在客户端和服务器之间传递的,因此也存在被窃取的风险。 但是一般虽然 Cookie 被盗取了,但是用户只泄漏了一个 Session ID,私密信息暂时没有被泄露的风险 Session ID 便于服务端进行客户端有效性的管理,比如异地登录。 可以通过 HTTPS 和设置合适的 Cookie 属性(如 HttpOnly 和 Secure)来增强安全性

2.4 用途
  • 用户认证和会话管理
  • 存储用户的临时数据(如购物车内容)
  • 实现分布式系统的会话共享(通过将会话数据存储在共享数据库或缓存中)
2.5 模拟Session行为

session.hpp

Session对象用来保存用户的基本信息,SessionManager类维护了当前所有的session对象,可以通过sessionid来索引session对象

#pragma once
#include <string>
#include <time.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#include <memory>
#include <unordered_map>
#include "Log.hpp"class Session
{
public:Session(const std::string &username, const std::string &passward): _username(username), _passward(passward){_create_time = time(nullptr); // 获取时间戳就行了,后面实际需要,就转化就转换一下}std::string Username(){return _username;}private:// 用户的信息std::string _username;std::string _passward;std::string _create_time;// 还可以定义其他的用户信息,例如浏览记录等等
};using session_ptr = std::shared_ptr<Session>;
class SessionManager
{
public:SessionManager(){srand(time(nullptr));}~SessionManager(){}std::string AddSession(session_ptr s){uint32_t randomid = rand() + time(nullptr); // 随机数+时间戳,实际有形成sessionid的库,比如boost uuid库,或者其他第三方库等std::string sessionid = std::to_string(randomid);_sessions.insert(std::make_pair(sessionid, s));return sessionid;}session_ptr GetSession(std::string sessionid){if (_sessions.find(sessionid) == _sessions.end())return nullptr;elsereturn _sessions[sessionid];}private:std::unordered_map<std::string, session_ptr> _sessions; // sessionid索引session对象
};

 如果检测到sessionid是空的话,说明这个用户是第一次访问服务器,通过登录的信息生成一个session对象,并将其插入到sessionmanager中维护起来获取一个sessionid,通过cookie的方式发送给客户端

当该用户后再次访问时,通过它的sessionid就可以识别他的身份进行业务处理,假设别人在另一台设备上登陆了该用户的账号,那就可以结合具体业务,例如跟据用户的使用偏好、是否异地登录等等,检测是否为非法登录,若是,我们在进行人脸识别登验证,不通过则直接在后台删除它的sessionid,让其失效即可

    std::string HandlerHttpRequest(std::string &reqstr){std::cout << "---------------------------------------" << std::endl;std::cout << reqstr;std::cout << "---------------------------------------" << std::endl;HttpRequest req;req.DeSerialize(reqstr);HttpResponse resp;static int number = 0;if (req.Url() == "/login") // 模拟登录{std::string sessionid = req.Sessionid();if (sessionid.empty()) // 说明客户端第一次访问服务器,那就给客户端形成一个sessionid发送给他{std::string user = "user-" + std::to_string(number++);session_ptr s = std::make_shared<Session>(user, "123456");sessionid = _session_manager->AddSession(s);LOG(DEBUG, "%s 被添加, sessionid是: %s\n", user.c_str(), sessionid.c_str());resp.AddHeader("Set-Cookie", "sessionid=" + sessionid);}}else{std::string sessionid = req.Sessionid();if (!sessionid.empty()){session_ptr s = _session_manager->GetSession(sessionid);// 这个地方有坑,一定要判断服务器端session对象是否存在,因为可能测试的时候// 浏览器还有历史sessionid,但是服务器重启之后,session对象没有了.if (s != nullptr){LOG(DEBUG, "%s 正在活跃.\n", s->Username().c_str());}else{LOG(DEBUG, "cookie : %s 已经过期, 需要清理\n", sessionid.c_str());}}}resp.AddCode(200, _code_to_desc[200]);resp.AddBodyText("<html><h1>helloworld</h1></html>");std::string respstr = resp.Serialize();return respstr;}

相关文章:

[网络]HTTP协议 Cookie与Session

一、Cookie 1.1 定义 HTTP Cookie&#xff08;也称为 Web Cookie、浏览器 Cookie 或简称 Cookie&#xff09;是服务器发送到 用户浏览器并保存在浏览器上的一小块数据&#xff0c;它会在浏览器之后向同一服务器再次发 起请求时被携带并发送到服务器上。通常&#xff0c;它用于…...

安宝特科技 | AR眼镜在安保与安防领域的创新应用及前景

随着科技的不断进步&#xff0c;增强现实&#xff08;AR&#xff09;技术逐渐在多个领域展现出其独特的优势&#xff0c;尤其是在安保和安防方面。AR眼镜凭借其先进的功能&#xff0c;在机场、车站、海关、港口、工厂、园区、消防局和警察局等行业中为安保人员提供了更为高效、…...

2024 第十二届重庆国际植保双交会暨新型肥料农药产业博览会

2024 第十二届重庆国际植保双交会暨新型肥料农药产业博览会&#xff0c;引领农业新未来 农业&#xff0c;是人类生存的基石&#xff0c;是社会发展的保障。而肥料和农药&#xff0c;作为农业生产的重要投入品&#xff0c;其品质和技术的不断创新&#xff0c;直接关系着农业的可…...

用“说”智能控制灯具开关语音识别芯片NRK3603

用“说”智能控制灯具开关是一种基于语音识别技术的智能家居设备&#xff0c;它通过内置的语音识别芯片&#xff0c;利用离线识别算法&#xff0c;将用户的语音指令实现对灯具的控制&#xff0c;NRK3603语音识别芯片成为客户低成本的离线语音识别方案。 功能特性&#xff1a; …...

APS开源源码解读: 排程工具 optaplanner

抽象层次非常好&#xff0c;广义优化工具。用于排产没有复杂的落地示例 https://github.com/apache/incubator-kie-optaplanner/blob/main/optaplanner-examples/src/main/java/org/optaplanner/examples/projectjobscheduling/app/ProjectJobSchedulingApp.javahttps://github…...

AMEYA360:村田量产用于汽车市场的高可靠性0603M铜电极负温度系数NTC热敏电阻

株式会社村田制作所开发了0603M尺寸(0.60.30.3mm)铜电极负温度系数(NTC)热敏电阻&#xff0c;型号分别是“NCU03XH103F6SRL”和“NCU03XH103F60RL”&#xff0c;该新品扩充了NCU系列的产品尺寸阵容&#xff0c;满足了汽车市场应用中电路板的高密度化和小型化、以及对电子部件的…...

代码随想录第十天|150.逆波兰表达式求值 239.滑动窗口的最大值 347.前K个高频元素

150.逆波兰表达式求解 思路&#xff1a;做过 使用stoi &#xff1a;字符串转数字 class Solution { public:int cal(int num1,int num2,char c){int res;if(c){resnum1num2;}if(c-){resnum2-num1;}if(c*){resnum1*num2;}if(c/){resnum2/num1;}return res;}int evalRPN(vector…...

[阅读笔记]《解读基金—我的投资观与实践》— 季凯帆

&#x1f4e2;博客主页&#xff1a;https://loewen.blog.csdn.net&#x1f4e2;欢迎点赞 &#x1f44d; 收藏 ⭐留言 &#x1f4dd; 如有错误敬请指正&#xff01;&#x1f4e2;本文由 丶布布原创&#xff0c;首发于 CSDN&#xff0c;转载注明出处&#x1f649;&#x1f4e2;现…...

2.3之前

1. 2. freertos基础时钟:freertos自动的采用systick定时器,作为freertos基础时钟&#xff0c;systick定时器只有定时中断功能&#xff0c;1ms中断一次。...

处理器基础知识——cache

本文节选自书籍《大话处理器&#xff1a;处理器基础知识读本》 PDF版本可以访问我的网盘通过网盘分享的文件&#xff1a;大话处理器&#xff1a;处理器基础知识读本.pdf 提取码: 1234 0 什么是 Cache 随处可见的Cache–技术来源于生活 使用电脑的人对 Cachc 并不会陌生&#…...

操作系统的运行环境

1.处理器的运行模式 目态 也叫用户态&#xff0c; 执行非特权指令&#xff1a;不能直接访问系统中的软硬件资源&#xff0c;仅仅可以访问用户地址空间。 用户应用程序运行在目态。 管态 也叫内核态&#xff0c; 可执行除访管指令外的任意指令&#xff0c;包括特权指令&…...

如何在 Selenium 中获取网络调用请求?

引言 捕获网络请求对于理解网站的工作方式以及传输的数据至关重要。Selenium 作为一种 Web 自动化工具,可以用于捕获网络请求。本文将讨论如何使用 Selenium 在 Java 中捕获网络请求并从网站检索数据。 我们可以使用浏览器开发者工具轻松捕获网络请求或日志。大多数现代 Web…...

IP学习——oneday

1.什么是网络&#xff1f;为什么需要网络&#xff1f; 空间&#xff0c;时间&#xff1b;传统的邮件传输要考虑到距离&#xff0c;网络解决了空间距离&#xff08;太远&#xff09;、解决了时间问题&#xff08;旧音乐等&#xff09; 云:面向客户的虚拟化服务 运营商公司主营…...

2024 年高教社杯全国大学生数学建模竞赛 C 题 农作物的种植策略(详细思路+matlab代码+python代码+论文范例)

持续更新中,2024年数学建模比赛思路代码论文都会发布到专栏内,只需订阅一次! 完整论文+代码+数据结果链接在文末! 一、第一问 问题描述:假定各种农作物未来的预期销售量、种植成本、亩产量和销售价格相对于 2023 年保持稳定,每季种植的农作物在当季销售。如果某种作物每…...

软件工程知识点总结(1):软件工程概述

1 什么是软件&#xff1f; 定义&#xff1a;计算机系统中的程序及其文档。 ——程序是计算机任务的处理对象和处理规模的描述&#xff1b; ——文档是为了便于了解程序所需要的阐明性资料。 2 软件的特点&#xff1f; 软件是无形的&#xff0c;不可见的逻辑实体 ——它的正确与…...

热烈庆祝中国科学技术大学建校六六周年

卡西莫多的诗文集2022-2024.9月6-校庆国庆专版 欢迎分享 通过网盘分享的文件&#xff1a;卡西莫多的诗文集2022-2024.9月6-A5-校庆国庆专版.pdf 链接: 百度网盘 请输入提取码 提取码: umpm...

iptables持久化命令:netfilter-persistent save

在Linux上&#xff0c;使用netfilter-persistent命令可以保存iptables防火墙规则&#xff0c;确保它们在系统重启后仍然有效。以下是如何使用netfilter-persistent来保存iptables规则的步骤&#xff1a; 打开终端&#xff1a;首先&#xff0c;你需要打开Linux系统的终端。保存…...

elementUI table 给表头添加气泡显示(鼠标悬浮显示注释)

elementUI table 给表头添加气泡显示&#xff08;鼠标悬浮显示注释&#xff09; 前言&#xff1a;文档显示&#xff1a;&#xff08;使用插槽&#xff0c;我看看到底是怎么个事儿&#xff09;文档代码:修改后的效果&#xff1a;页面效果&#xff1a; 前言&#xff1a; 公司出现…...

Web3社交新经济,与 SOEX 实现无缝交易的高级安全性

出于充分的理由&#xff0c;安全性是交易中至关重要的考虑因素。每个人都应该确保自己的资金在交易时是安全的。由于 &#xff33;&#xff2f;&#xff25;&#xff38; 充当您与交易所的最佳连接&#xff0c;因此必须强调的是&#xff0c;该系统不会引发任何安全问题。 &a…...

Python和MATLAB(Java)及Arduino和Raspberry Pi(树莓派)点扩展函数导图

&#x1f3af;要点 反卷积显微镜图像算法微珠图像获取显微镜分辨率基于像素、小形状、高斯混合等全视野建模基于探测器像素经验建模荧光成像算法模型傅里叶方法计算矢量点扩展函数模型天文空间成像重建二维高斯拟合天体图像伽马射线能量和视场中心偏移角标量矢量模型盲解卷积和…...

使用isolation: isolate声明隔离混合模式

在CSS中&#xff0c;isolation 属性与混合模式&#xff08;如 mix-blend-mode 和 background-blend-mode&#xff09;并不直接相关&#xff0c;但它确实可以影响元素如何与其他元素进行渲染&#xff0c;尤其是在涉及到堆叠上下文&#xff08;stacking contexts&#xff09;和复…...

93. UE5 GAS RPG 应用负面效果表现

在上一篇文章里&#xff0c;我们实现了添加负面效果GE&#xff0c;并且在添加GE时&#xff0c;也会给角色应用一个负面效果标签作为标识。在这一篇里&#xff0c;我们将通过负面效果标签标识&#xff0c;应用角色身上展现对应的负面效果的表现。 我们将在这篇文章里添加一个自定…...

TCP 和 UDP 区别

UDP UDP&#xff08;用户数据报协议&#xff0c;User Datagram Protocol&#xff09;是一种无连接的网络传输协议&#xff0c;提供了简单的消息传送服务。UDP位于传输层&#xff0c;允许应用程序向其他主机发送封装在IP数据报中的消息&#xff0c;而无需先建立连接。由于UDP不…...

免费2024柜台租赁经营合同范本模板下载分享

今天看到这个合同范本都拿来卖钱,我直接分享出来2024年最新的范本模板随便下,免费的 柜台租赁经营合同GF—2013—0603.docx: https://url51.ctfile.com/f/20096151-1353625109-4285d2?p1605 (访问密码: 1605) 柜台租赁经营合同GF—2013—0603.pdf: https://url51.ctfile.com/…...

模型和算力看板:Compute DashBoard

AGI 之路 AGI&#xff08;通用人工智能&#xff09;是整个计算机科学的圣杯&#xff0c;算力的增长和模型能力的提升&#xff08;算法和数据&#xff09;缺一不可。作为一个新质生产力&#xff0c;构建一个合理的评价体系是常用的方法论。针对模型和算力的评价&#xff0c;有类…...

Python加载 TorchScript 格式的 ResNet18 模型分类该模型进行预测并输出预测的类别和置信度

首先加载预训练的 ResNet18 模型。将模型设置为评估模式&#xff0c;以确保特定层&#xff08;如 Dropout 和 BatchNorm&#xff09;在评估时具有确定性的行为。创建一个形状为 (1, 3, 224, 224) 的随机张量作为示例输入。使用 torch.jit.trace 函数追踪模型在给定示例输入上的…...

学习笔记--MybatisPlus

官网&#xff1a;MyBatis-Plus &#x1f680; 为简化开发而生 快速入门 入门案例 引入MybatisPlus的起步依赖 定义Mapper 问题&#xff1a; MybatisPlus中Invalid bound statement (not found): com.itheima.mp.mapper.UserMapper.insert 一定要指定实体类&#xff01;&am…...

【机器学习】XGBoost的用法和参数解释

一、XGBoost的用法 流程&#xff1a; 代码案例&#xff1a; 二、XGBoost的几大参数 1、一般参数&#xff0c;用于集成算法本身 ①n_estimators 集成算法通过在数据上构建多个弱 评估器&#xff0c;汇总所有弱评估器的建模结果&#xff0c;以获取比单个模型更好的回归或分类…...

Vivado 约束

步骤5&#xff1a;保存约束 约束管理是设计流程的重要一步&#xff0c;Vivado设计套件 为您提供了在现有约束文件中添加新约束、覆盖的灵活性 现有约束&#xff0c;或创建新的约束文件以跟踪设计更改或完成 缺少约束。 您为设计创建了一些定时异常&#xff0c;但这些异常仅存在…...

如何在Excel中创建一个VBA宏,并设置一个按钮来执行这个宏

下面是一个详细的步骤指南 步骤1&#xff1a;创建VBA宏 1. 打开Excel并按 Alt F11 打开VBA编辑器。 2. 在VBA编辑器中&#xff0c;选择 Insert > Module 来插入一个新的模块。 3. 将以下代码粘贴到模块中&#xff1a; vba Sub CreateNewSheet() 声明一个工作表对象Dim …...