cookie的使用方法
简介
cookie是一种在Web浏览器中存储用户信息的技术。cookie通常用于存储用户的登录信息、购物车信息、浏览历史等。cookie是由服务器端生成的,浏览器会将cookie保存到本地,并在每次请求时将cookie发送到服务器端。服务器端可以根据cookie中的信息来判断用户的身份,并返回相应的内容。
工作原理
cookie的工作原理如下:
- 服务器端生成cookie,并将cookie发送到浏览器。 服务器同时设置一个session,将sessionid存储在cookie中,返回给浏览器。同时服务器也会将sessionid存储在服务器端,一般是保存在 客户端请求fd中。
- 浏览器将cookie保存到本地。
- 浏览器在每次请求时将cookie发送到服务器端。
- 服务器端根据cookie中的sessionid, 然后拿这个sessionid值与fd中保存的sessionid进行比较,看一下当前访问的用户是否登录过了。
使用环境
这里提到的cookies是在esp32中使用的。使用的是 esp-idf 中的httpd库。位置:components/esp_http_server
参考示例:examples/protocols/http_server/restful_server
使用方法
1. 初始化cookie
生成一个cookies里面用到的token的值。作为cookie的值,一般是一个随机数。
char* token = malloc(33);
snprintf(token,33, "%08lx%08lx%08lx%08lx", esp_random(), esp_random(), esp_random(), esp_random());
2. 设置cookie
char cookie[80];
snprintf(cookie, sizeof(cookie), "session=%s; Path=/; HttpOnly", token);
httpd_resp_set_hdr(req, "Set-Cookie", cookie);
httpd_resp_set_hdr
是httpd的函数,用于设置响应头。Set-Cookie
是响应头的名称,cookie
是响应头的值。通过这个函数,服务器登录成功后,就会获取得到cookie的值。 这个值,当用户再次访问服务器时,就会将这个值发送到服务器端。
3. 保存服务器端的sessionid
在这里将token
保存到服务器端的sessionid中。
httpd_sess_set_ctx(req->handle, httpd_req_to_sockfd(req), token, free); // 自动释放内存
重点理解httpd_sess_set_ctx
是httpd的函数,用于设置session的上下文。req->handle
是请求句柄,httpd_req_to_sockfd(req)
是请求的socket文件描述符,token
是session的上下文,free
是session的上下文释放函数。通过这个函数,服务器端将sessionid保存到服务器端的session中。 free 是传入的一个函数指针,用于释放内存。这里的内存,实际上就是传入的token。当用户断开连接或是退出登录时,就会调用这个函数来释放内存。
所以这里的 token
必须是一个动态分配的内存,否则会报错。在第1步
时的代码:char* token = malloc(33);
,不能使用栈上的内存,因为栈上的内存会随着函数的返回而被释放。也不能使用全局变量,因为全局变量在程序运行期间一直存在,不能使用free
进行释放。
4.获取cookie并进行验证
当用户访问服务器时,服务器会自动获取来自客户端的cookie。
static esp_err_t verify_session(httpd_req_t *req)
{
// 检查是否有session
char *sess_ctx = httpd_sess_get_ctx(req->handle, httpd_req_to_sockfd(req));
if (!sess_ctx) {
ESP_LOGE(REST_TAG, "Session not found");
httpd_resp_send_err(req, HTTPD_401_UNAUTHORIZED, "{\"msg\":\"Session not found\"}");
return ESP_FAIL;
}
// 检查cookie是否存在
char cookie[50];
esp_err_t err = httpd_req_get_hdr_value_str(req, "Cookie",cookie,50);
if (err) {
ESP_LOGE(REST_TAG, "Cookie not found");
httpd_resp_send_err(req, HTTPD_401_UNAUTHORIZED, "{\"msg\":\"Cookie not found\"}");
return ESP_FAIL;
}
// 检查cookie中的session是否与请求中的session匹配
char *session = strstr(cookie, "session=");
if (!session || strncmp(session + 8, sess_ctx, 32) != 0) {
ESP_LOGE(REST_TAG, "Invalid session");
httpd_resp_send_err(req, HTTPD_401_UNAUTHORIZED, "{\"msg\":\"Invalid session\"}");
return ESP_FAIL;
}
// 如果验证成功,返回 ESP_OK
ESP_LOGI(REST_TAG, "Session verified successfully");
return ESP_OK;
}