HTTP Cookie深入解析:Web会话追踪的秘密

HTTP Cookie深入解析:Web会话追踪的秘密

🍑个人主页:Jupiter.🚀 所属专栏:Linux从入门到进阶欢迎大家点赞收藏评论😊

在这里插入图片描述
在这里插入图片描述

目录


当我们登录了B站过后,为什么下次访问B站就不需要登陆了?

  • 问题:B 站是如何认识我这个登录用户的?
  • 问题:HTTP 是无状态,无连接的,怎么能够记住我?

定义

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

工作原理

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

分类

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

安全性

  • 由于 Cookie 是存储在客户端的,因此存在被篡改或窃取的风险。

用途

  • 用户认证和会话管理(最重要)
  • 跟踪用户行为
  • 缓存用户偏好等
  • 比如在 chrome 浏览器下,可以直接访问:link
  • HTTP 存在一个报头选项:Set-Cookie, 可以用来进行给浏览器设置 Cookie值。
  • HTTP 响应报头中添加,客户端(如浏览器)获取并自行设置并保存Cookie。

服务器发送Cookie

  • 当客户端(如浏览器)首次请求服务器资源时,服务器可能会在HTTP响应中包含一个或多个Set-Cookie头部。这些Set-Cookie头部指示客户端存储特定的信息(即Cookie)。
  • 每个Set-Cookie头部都包含了Cookie的名称、值以及可选的属性,如过期时间(Expires/Max-Age)、作用域(Path)、安全性要求(Secure)、跨站策略(SameSite)以及是否只能通过HTTP接口访问(HttpOnly)等。

客户端接收并保存Cookie

  • 浏览器接收到包含Set-Cookie头部的HTTP响应后,会解析这些头部,并根据其中的指令将Cookie存储到本地。
  • 存储的Cookie会包含名称、值以及所有相关的属性。
  • 浏览器会根据Cookie的过期时间和其他属性来决定何时删除这些Cookie。

客户端发送Cookie

  • 当浏览器再次向同一服务器(或符合Cookie作用域的其他服务器)发送请求时,它会自动检查是否有与该请求相关的Cookie。如果有,浏览器会将这些Cookie附加到HTTP请求的Cookie头部,并发送给服务器。服务器接收到请求后,可以从Cookie头部中读取这些Cookie,并根据需要处理它们。

基本格式

在这里插入图片描述


完整的 Set-Cookie 示例

在这里插入图片描述


时间格式必须遵守 RFC 1123 标准,具体格式样例:Tue, 01 Jan 2030 12:34:56 GMT 或者 UTC(推荐)。
关于时间解释

  • Tue: 星期二(星期几的缩写)
  • , : 逗号分隔符
  • 18: 日期(两位数表示)
  • Thu: 月份的缩写
  • 2024: 年份(四位数)
  • 12:34:56: 时间(小时、分钟、秒)
  • GMT: 格林威治标准时间(时区缩写)

GMT 和 UTC 都曾是或现在是国际上重要的时间标准,但由于地球自转的不规则性和原子钟的精确性,UTC 已经成为了全球性的标准时间,而 GMT 则更多被用作历史和地理上的参考。

关于其他可选属性的解释

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

以下是对 Set-Cookie 头部字段的简洁介绍

注意事项

  • 每个 Cookie 属性都以分号(;)和空格( )分隔。
  • 名称和值之间使用等号(=)分隔。
  • 如果 Cookie 的名称或值包含特殊字符(如空格、分号、逗号等),则需要进行 URL 编码。

Cookie 的生命周期

  • 如果设置了 expires 属性,则 Cookie 将在指定的日期/时间后过期。
  • 如果没有设置 expires 属性,则 Cookie 默认为会话 Cookie,即当浏览器关闭时过期。

安全性考虑

  • 使用 secure 标志可以确保 Cookie 仅在 HTTPS 连接上发送,从而提高安全性。
  • 使用 HttpOnly 标志可以防止客户端脚本(如 JavaScript)访问 Cookie,从而防止 XSS 攻击。
  • 通过合理设置 Set-Cookie 的格式和属性,可以确保 Cookie 的安全性、有效性和可访问性,从而满足 Web 应用程序的需求。

测试 cookie 的关键性完整代码全部附在最后。

  • 测试 cookie 写入到浏览器
 resp.AddHeader("Set-Cookie: username=zhangsan;");//响应中添加一行报头即可
  • 测试自动提交
  • 测试写入过期时间
    • 这里要由我们自己形成 UTC 统一标准时间:
//时间格式如: expires=Thu, 18 Dec 2024 12:00:00 UTC 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 GetWeekDayName(int day){ std::vector<std::string> weekdays ={"Sun","Mon","Tue","Wed","Thu","Fri","Sat"};return weekdays[day];} std::string ExpireTimeUseRfc1123(int t)// 秒级别的未来UTC时间{ time_t timeout =time(nullptr)+ t;structtm*tm =gmtime(&timeout);// 这里不能用localtime,因为localtime是默认带了时区的. gmtime获取的就是UTC统一时间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;}
在这里插入图片描述
  • 测试路径 path

提交到非/a/b 路径下

  • 比如:http://8.137.19.140:8888/a/x
  • 比如:http://8.137.19.140:8888/
  • 比如:http://8.137.19.140:8888/x/y
在这里插入图片描述


单独使用 Cookie,有什么问题?

  • 我们写入的是测试数据,如果写入的是用户的私密数据呢?比如,用户名密码,浏览痕迹等。
  • 本质问题在于这些用户私密数据在浏览器(用户端)保存,非常容易被人盗取,更重要的是,除了被盗取,还有就是用户私密数据也就泄漏了。

Cookie测试代码

#pragmaonce#include<iostream>#include<string>#include<sstream>#include<vector>#include<memory>#include<ctime>#include"TcpServer.hpp"const std::string HttpSep ="\r\n";// 可以配置的const std::string homepage ="index.html";const std::string wwwroot ="./wwwroot";classHttpRequest{public:HttpRequest():_req_blank(HttpSep),_path(wwwroot){}boolGetLine(std::string &str, std::string *line){auto pos = str.find(HttpSep);if(pos == std::string::npos)returnfalse;*line = str.substr(0, pos);// \r\n str.erase(0, pos + HttpSep.size());returntrue;}boolDeserialize(std::string &request){ std::string line;bool ok =GetLine(request,&line);if(!ok)returnfalse; _req_line = line;while(true){bool ok =GetLine(request,&line);if(ok && line.empty()){ _req_content = request;break;}elseif(ok &&!line.empty()){ _req_header.push_back(line);}else{break;}}returntrue;}~HttpRequest(){}private:// http报文自动 std::string _req_line;// method url http_version std::vector<std::string> _req_header; std::string _req_blank; std::string _req_content;// 解析之后的内容 std::string _method; std::string _url;// /dira/dirb/x.html /dira/dirb/XX?usrname=100&&password=1234 /dira/dirb std::string _http_version; std::string _path;// "./wwwroot" std::string _suffix;// 请求资源的后缀};const std::string BlankSep =" ";const std::string LineSep ="\r\n";classHttpResponse{public:HttpResponse():_http_version("HTTP/1.0"),_status_code(200),_status_code_desc("OK"),_resp_blank(LineSep){}voidSetCode(int code){ _status_code = code;}voidSetDesc(const std::string &desc){ _status_code_desc = desc;}voidMakeStatusLine(){ _status_line = _http_version + BlankSep + std::to_string(_status_code)+ BlankSep + _status_code_desc + LineSep;}voidAddHeader(const std::string &header){ _resp_header.push_back(header+LineSep);}voidAddContent(const std::string &content){ _resp_content = content;} std::string Serialize(){MakeStatusLine(); std::string response_str = _status_line;for(auto&header : _resp_header){ response_str += header;} response_str += _resp_blank; response_str += _resp_content;return response_str;}~HttpResponse(){}private: std::string _status_line; std::vector<std::string> _resp_header; std::string _resp_blank; std::string _resp_content;// body// httpversion StatusCode StatusCodeDesc std::string _http_version;int _status_code; std::string _status_code_desc;};classHttp{private: 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 GetWeekDayName(int day){ std::vector<std::string> weekdays ={"Sun","Mon","Tue","Wed","Thu","Fri","Sat"};return weekdays[day];} std::string ExpireTimeUseRfc1123(int t)// 秒级别的未来UTC时间{ time_t timeout =time(nullptr)+ t;structtm*tm =gmtime(&timeout);// 这里不能用localtime,因为localtime是默认带了时区的. gmtime获取的就是UTC统一时间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;}public:Http(uint16_t port){ _tsvr = std::make_unique<TcpServer>(port, std::bind(&Http::HandlerHttp,this, std::placeholders::_1)); _tsvr->Init();} std::string ProveCookieWrite()// 证明cookie能被写入浏览器{return"Set-Cookie: username=zhangsan;";}// resp.AddHeader(ProveCookieWrite()); //测试cookie被写入与自动提交 std::string ProveCookieTimeOut(){return"Set-Cookie: username=zhangsan; expires="+ExpireTimeUseRfc1123(60)+";";// 让cookie 1min后过期} std::string ProvePath(){return"Set-Cookie: username=zhangsan; path=/a/b;";} std::string ProveOtherCookie(){return"Set-Cookie: passwd=1234567890; path=/a/b;";} std::string HandlerHttp(std::string request){ HttpRequest req; req.Deserialize(request); req.DebugHttp(); lg.LogMessage(Debug,"%s\n",ExpireTimeUseRfc1123(60).c_str()); HttpResponse resp; resp.SetCode(200); resp.SetDesc("OK"); resp.AddHeader("Content-Type: text/html");// resp.AddHeader(ProveCookieWrite()); //测试cookie被写入与自动提交// resp.AddHeader(ProveCookieTimeOut()); //测试过期时间的写入// resp.AddHeader(ProvePath()); // 测试路径 resp.AddHeader(ProvePath()); resp.AddHeader(ProveOtherCookie()); resp.AddContent("<html><h1>helloworld</h1></html>");return resp.Serialize();}voidRun(){ _tsvr->Start();}~Http(){}private: std::unique_ptr<TcpServer> _tsvr;};

Read more

Trae IDE 安装与使用保姆级教程:字节跳动的 AI 编程神器

一、Trae 是什么? Trae(发音 /treɪ/)是字节跳动推出的 AI 原生集成开发环境(AI IDE),于 2025 年 1 月正式发布。与传统的 IDE + AI 插件组合不同,Trae 从底层架构上就将 AI 能力深度集成,实现了真正意义上的"AI 主导开发"。 核心定位 Trae 以 “自主智能体(Agent)” 为核心定位,彻底重构了传统开发流程: * Chat 模式:智能代码补全、问答、解释和优化 * Builder 模式:自然语言一键生成完整项目框架 * SOLO 模式:AI 自主规划并执行开发任务 版本划分 版本定位核心特色适用人群Trae

保姆级教程:Windows本地部署Ollama+OpenClaw,打造你的AI赚钱系统(APP开发/量化/小说/剪辑)

摘要:想用AI搞钱但卡在技术门槛?本文手把手教你用一台Windows电脑,零成本本地部署Ollama大模型+OpenClaw智能中枢,赋予AI开发APP、量化分析、编写小说、剪辑辅助等“赚钱技能”。全程无需编程基础,跟着鼠标点、照着命令敲,即可拥有24小时待命的AI员工。 一、写在前面 很多朋友对AI变现跃跃欲试,却常被这些问题劝退: * 云端部署太贵,API调用怕浪费钱 * 技术文档看不懂,不知道从哪下手 * 数据隐私担忧,不敢把敏感资料上传 其实,你手头那台Windows电脑完全能胜任!本文将带你搭建一套完全本地化、免费、可扩展的AI生产力系统,让AI帮你写代码、分析表格、生成文案、处理视频,真正把AI变成你的“赚钱工具”。 系统架构: * 本地大脑:Ollama + DeepSeek模型,负责理解任务、生成内容 * 智能中枢:OpenClaw(原名OpenClaude),负责调用各类工具(Skill) * 赚钱技能:通过安装Skill包,让AI具备特定领域的实操能力 适用人群:

2026年3月13日AI热点:芯片大战、Agent爆发、安全争议

2026年3月13日AI热点:芯片大战、Agent爆发、安全争议 今日AI圈发生了什么?十大热点一文打尽 ChatGPT o3 pro | Claude 3.7 | Gemini 2.5 pro免费用 👉 AI工具集 今天的AI圈依然热闹非凡!从芯片巨头的大手笔投入,到Agent时代的全面爆发,再到AI安全争议愈演愈烈…让我带你一篇看完今日AI十大热点! 🔥 十大AI新闻 1. Anthropic 起诉美国国防部 Anthropic就供应链风险认定起诉五角大楼,称这一认定可能让其损失数十亿美元。特朗普政府表示不排除对Anthropic采取进一步行动。 2. Nvidia 投资260亿美元开发开源模型 最新文件显示,Nvidia计划投入260亿美元构建开源权重AI模型,展现其对开源生态的承诺。 3. Meta 发布4款新AI芯片 Meta推出了MTIA 300芯片,用于训练Instagram和Facebook的排序推荐系统。MTIA 400/450/500将在2027年前支持生成式AI推理。 4. Google Gemini 登陆 Chrome

18款免费AI 生成3D模型工具盘点

18款免费AI 生成3D模型工具盘点

18个免费AI 3D模型生成平台合集:零基础也能玩转三维创作 随着生成式AI技术的爆发,3D建模正从专业领域走向大众。以往需要数天甚至数周的建模工作,如今通过AI工具几分钟就能完成。以下整理了18个支持免费使用的AI 3D模型生成平台,涵盖不同创作场景,尤其纳入了人气工具open3d.art,无论你是设计师、开发者还是创意爱好者,都能找到适合自己的高效工具。 核心推荐平台 1. Open3d AI 作为兼具专业性与易用性的热门平台,open3d.art支持文本和图片双模态生成,1分钟内即可输出高质量3D模型,复杂模型生成也仅需5-10分钟。平台内置50万+模型资产库,生成的模型包含精细几何结构与PBR纹理,支持GLB、OBJ、FBX、STL等全格式导出,完美兼容Blender、Unity等主流软件。免费用户可无限制生成基础模型,商用授权完全免费,特别适合游戏开发、建筑可视化、产品原型设计等场景,活跃用户已超1万人。 2. Meshy 华人团队打造的国际知名平台,免费版每月赠送200积分,支持文生3D、图生3D双模式,1-2分钟即可完成白膜+贴图生成。核心优势在于PBR全贴图