一、背景
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;
};