一、背景
HTTP协议是无状态无连接的。
无状态:服务器不会保存客户端历史请求记录,每一次请求都是全新的。
无连接:服务器应答后关闭连接,每次请求都是独立的。
无状态就导致服务器不认识每一个请求的客户端是否登陆过。
这时我们就可以用 Cookie 和 Session 来记录客户端用户信息。
二、Cookie
1、理解
Cookie:是服务器发送到用户浏览器并保存在浏览器上的一小块数据,用于下次对服务器请求时加上客户端信息。
2、原理
3、分类
会话 Cookie(Session 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、理解
2、原理
实际上 session_id 是一个类,里面不仅记录用户各种登录属性,还有许多关于用户的细节,这样应答不会显示返回用户私密信息,session_id 里面也有属性能判断当前用户请求中的 session_id是否是合法的,以此来防止 session_id 被盗取。如果非法就让 session_id 失效。
3、用途
(1)用户认证,会话管理
(2)存储用户临时数据
(3)实现分布式系统会话管理
4、代码
实现一个session_id类
#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;
};