HTTP中的Cookie与Session

一、背景

HTTP协议是无状态无连接的。

无状态:服务器不会保存客户端历史请求记录,每一次请求都是全新的。

无连接:服务器应答后关闭连接,每次请求都是独立的。

无状态就导致服务器不认识每一个请求的客户端是否登陆过。

这时我们就可以用 Cookie 和 Session 来记录客户端用户信息。

二、Cookie

1、理解

Cookie:是服务器发送到用户浏览器并保存在浏览器上的一小块数据,用于下次对服务器请求时加上客户端信息。

2、原理


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

3、分类

会话 Cookie(Session Cookie)

在浏览器关闭时失效。一般是内存级存储,浏览器启动是一个进程,在进程内部保存 Cookie 数据。
持久 Cookie ( Persistent Cookie)
带有明确的过期日期或持续时间,可以跨多个浏览器会话存在。一般是文件级 Cookie 会在自己工作目录下保存 Cookie 数据。

4、Cookie 基本格式

Set-Cookie:<name>=<value>

<name> 相当于 key,<value> 相当于 value

举例:Set-Cookie: username=peter; expires=Thu, 18 Dec 2024 12:00:00 UTC; path=/;domain=.example.com; secure; HttpOnly

**expires:**Cookie 过期时间,如果没有设置过期时间,则 Cookie 默认为会话 Cookie,即当浏览器关闭时过期。

**时间格式:**RFC 1123标准,GMT格林威治标准时间,UTC协调世界时

**path:**限定 Cookie 作用范围路径,/表示根目录,在指定域下都能使用

**domain:**仅使用HTTPS协议才能发送 Cookie

**HttpOnly:**意味着 Cookie 不能被客户端脚本(javascript)访问避免被攻击

但是单独使用 Cookie 由于存在客户端泄漏,所以引入 Session

三、Session

1、理解

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

2、原理

实际上 session_id 是一个类,里面不仅记录用户各种登录属性,还有许多关于用户的细节,这样应答不会显示返回用户私密信息,session_id 里面也有属性能判断当前用户请求中的 session_id是否是合法的,以此来防止 session_id 被盗取。如果非法就让 session_id 失效。

3、用途

(1)用户认证,会话管理

(2)存储用户临时数据

(3)实现分布式系统会话管理

4、代码

实现一个session_id类

cpp 复制代码
#pragma once
#include <iostream>
#include <string>
#include <memory>
#include <ctime>
#include <unistd.h>
#include <unordered_map>
// 用来进行测试说明
class Session
{
    public:
    Session(const std::string &username, const std::string &status)
    :_username(username), _status(status)
    {
        _create_time = time(nullptr); // 获取时间戳就行了,后面实际需要,就转化就转换一下
    }
    ~Session()
    {}
    
    public:
    std::string _username;
    std::string _status;
    uint64_t _create_time;
    //当然还可以再加任何其他信息,看你的需求
    };

using session_ptr = std::shared_ptr<Session>;

class SessionManager
{
public:
    SessionManager()
    {
        srand(time(nullptr) ^ getpid());
    }
    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(const std::string sessionid)
    {
        if(_sessions.find(sessionid) == _sessions.end()) 
            return nullptr;
        return _sessions[sessionid];
    }
    ~SessionManager()
    {}
private:
    std::unordered_map<std::string, session_ptr> _sessions;
};
相关推荐
BUG 4046 分钟前
LINUX--shell
linux·运维·服务器
菜鸟小白:长岛icetea12 分钟前
Linux零基础速成篇一(理论+实操)
linux·运维·服务器
hgdlip21 分钟前
手机IP地址:定义、查看与切换方法
网络协议·tcp/ip·智能手机
过过过呀Glik1 小时前
在 Ubuntu 服务器上添加和删除用户
linux·服务器·ubuntu
Java小白中的菜鸟3 小时前
centos7的磁盘扩容
linux·运维·服务器
黑客老陈4 小时前
面试经验分享 | 北京渗透测试岗位
运维·服务器·经验分享·安全·web安全·面试·职场和发展
dengjiayue4 小时前
tcp 的重传,流量控制,拥塞控制
网络协议·tcp/ip
橘子师兄4 小时前
如何在自己的云服务器上部署mysql
运维·服务器·mysql
@泽栖4 小时前
Docker 常用命令
运维·服务器·docker
黑子哥呢?5 小时前
Linux---防火墙端口设置(firewalld)
linux·服务器·网络