Cookie的全面了解

  1. 名称(Name): Cookie的唯一标识符。
  2. 值(Value): 存储的数据。
  3. 域(Domain): 指定Cookie的作用域,即哪些域名下的请求会携带该Cookie。
  4. 路径(Path): 指定Cookie的作用路径,即哪些路径下的请求会携带该Cookie。
  5. 过期时间(Expires/Max-Age): 指定Cookie的有效期,超过过期时间,Cookie将失效。
  6. 安全标志(Secure): 如果设置了Secure标志,Cookie只会在HTTPS连接中传输。
  7. HttpOnly标志: 如果设置了HttpOnly标志,JavaScript无法访问该Cookie。
  8. SameSite: 限制Cookie在跨站请求中的发送行为,帮助防止跨站请求伪造(CSRF)攻击。

HTTP Cookies 的工作原理是通过服务器和客户端之间的交互,来存储和传递小块数据,以便管理用户会话和偏好设置。以下是详细的工作原理:

当用户首次访问网站时,服务器会通过HTTP响应头 Set-Cookie 向浏览器发送一个Cookie。这个Cookie包含了名称、值、过期时间、路径、域、安全标志等属性。

示例响应头

http 复制代码
HTTP/1.1 200 OK
Set-Cookie: sessionId=abc123; Expires=Wed, 21 Oct 2025 07:28:00 GMT; Path=/; Domain=example.com; Secure; HttpOnly
Content-Type: text/html

<html>
  <body>...</body>
</html>

在这个示例中,服务器设置了一个名为 sessionId 的Cookie,值为 abc123,并包含多个属性:

  • Expires: 指定Cookie的过期时间。
  • Path: 指定Cookie的作用路径。
  • Domain: 指定Cookie的作用域。
  • Secure: 指定Cookie只能通过HTTPS连接传输。
  • HttpOnly: 指定Cookie只能通过服务器端脚本访问,无法通过客户端JavaScript访问。

浏览器接收到 Set-Cookie 头后,会将Cookie存储在本地,根据属性将其应用于指定的域名和路径。

每次用户向该网站发送请求时,浏览器会自动将符合条件的Cookie附加到请求头中,发送给服务器。请求头中的 Cookie 字段包含了所有匹配的Cookie。

示例请求头

http 复制代码
GET /resource HTTP/1.1
Host: example.com
Cookie: sessionId=abc123

服务器接收到请求后,会从请求头中的 Cookie 字段提取Cookie信息,根据这些信息来处理请求。例如,服务器可以根据 sessionId 来识别用户会话,验证用户身份。

使用Angular和Express设置和读取Cookies的例子

后端:Express.js

在Express.js中,我们可以使用 cookie-parser 中间件来处理HTTP Cookies。以下是一个示例,展示了如何在Express.js中设置和读取Cookies。

安装依赖

bash 复制代码
npm install express cookie-parser

服务器代码(server.js)

javascript 复制代码
const express = require('express');
const cookieParser = require('cookie-parser');

const app = express();
const port = 3000;

// 使用cookie-parser中间件
app.use(cookieParser());

// 设置Cookie的路由
app.get('/set-cookie', (req, res) => {
  res.cookie('username', 'john_doe', { maxAge: 900000, httpOnly: true });
  res.send('Cookie has been set');
});

// 读取Cookie的路由
app.get('/get-cookie', (req, res) => {
  const username = req.cookies.username || 'Guest';
  res.send(`Hello, ${username}`);
});

app.listen(port, () => {
  console.log(`Server is running at http://localhost:${port}`);
});

在这个示例中:

  • /set-cookie 路由设置一个名为 username 的Cookie,值为 john_doe,有效期为15分钟,并设置为 HttpOnly
  • /get-cookie 路由读取 username Cookie,如果不存在则返回 Guest

前端:Angular

在Angular中,我们可以使用 ngx-cookie-service 库来处理Cookies。以下是一个示例,展示了如何在Angular中设置和读取Cookies。

安装依赖

bash 复制代码
npm install ngx-cookie-service

模块配置(app.module.ts)

typescript 复制代码
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { HttpClientModule } from '@angular/common/http';
import { CookieService } from 'ngx-cookie-service';

import { AppComponent } from './app.component';

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule,
    HttpClientModule
  ],
  providers: [CookieService],
  bootstrap: [AppComponent]
})
export class AppModule { }

组件代码(app.component.ts)

typescript 复制代码
import { Component, OnInit } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { CookieService } from 'ngx-cookie-service';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {
  constructor(private http: HttpClient, private cookieService: CookieService) {}

  ngOnInit(): void {
    // 设置Cookie
    this.cookieService.set('clientCookie', 'angular_user', 1, '/');

    // 发送请求并包含Cookie
    this.http.get('http://localhost:3000/get-cookie', { withCredentials: true }).subscribe(response => {
      console.log(response);
    });
  }

  setServerCookie(): void {
    // 发送请求以设置服务器端Cookie
    this.http.get('http://localhost:3000/set-cookie', { withCredentials: true }).subscribe(response => {
      console.log(response);
    });
  }
}

在这个示例中:

  • 使用 ngx-cookie-service 设置一个名为 clientCookie 的Cookie,值为 angular_user,有效期为1天。
  • 通过 HttpClient 发送请求到服务器,设置和读取服务器端的Cookie。withCredentials: true 表示请求会携带跨域Cookie。 Cookie的过期是指当一个Cookie超过其设定的有效期后,浏览器会自动删除该Cookie。以下是Cookie过期过程的详细解释:

设置Cookie的过期时间

  1. Expires 属性

    • Expires 属性指定了Cookie的过期日期和时间。格式通常为UTC时间。

    • 示例

      http 复制代码
      Set-Cookie: sessionId=abc123; Expires=Wed, 21 Oct 2025 07:28:00 GMT
  2. Max-Age 属性

    • Max-Age 属性指定了Cookie的有效期(以秒为单位)。当该时间过去后,Cookie会过期并被删除。

    • 示例

      http 复制代码
      Set-Cookie: sessionId=abc123; Max-Age=3600

Cookie的过期过程

  1. 设置Cookie

    • 当服务器通过Set-Cookie头部设置一个Cookie时,可以指定该Cookie的过期时间或有效期。
    • 浏览器接收到Set-Cookie头部后,会根据指定的ExpiresMax-Age属性来存储Cookie。
  2. Cookie的存储

    • 浏览器会将Cookie存储在本地,并记录其过期时间或剩余的有效期。
  3. 检查过期时间

    • 每次浏览器发送请求时,都会检查已存储的Cookie的有效期。如果Cookie的过期时间已经到达或剩余的有效期已经为0,浏览器将不再发送该Cookie,并从本地存储中删除它。

示例代码

以下是一个示例,展示了如何通过JavaScript设置和检查Cookie的过期时间:

设置Cookie的函数

javascript 复制代码
function setCookie(name, value, expires) {
  let cookieString = `${name}=${value}; path=/`;
  if (expires) {
    cookieString += `; expires=${expires.toUTCString()}`;
  }
  document.cookie = cookieString;
}

// 设置一个有效期为1天的Cookie
const expiryDate = new Date();
expiryDate.setDate(expiryDate.getDate() + 1);
setCookie('username', 'john_doe', expiryDate);

读取和检查Cookie的函数

javascript 复制代码
function getCookie(name) {
  const cookieArray = document.cookie.split('; ');
  for (let i = 0; i < cookieArray.length; i++) {
    const cookiePair = cookieArray[i].split('=');
    if (cookiePair[0] === name) {
      return cookiePair[1];
    }
  }
  return null;
}

// 检查Cookie是否存在
const username = getCookie('username');
if (username) {
  console.log(`Username Cookie: ${username}`);
} else {
  console.log('Username Cookie has expired or does not exist');
}

使用HTTP Cookies存在一定的安全问题,可能会导致数据泄露和攻击。以下是一些常见的Cookie安全问题及其解决方案:

常见的Cookie安全问题

  1. 跨站脚本攻击(XSS)

    • 描述:攻击者通过注入恶意脚本,窃取Cookie数据。
    • 解决方案 :设置 HttpOnly 属性,防止JavaScript访问Cookie。此外,确保应用程序对用户输入进行充分的验证和过滤,防止恶意脚本注入。
  2. 跨站请求伪造(CSRF)

    • 描述:攻击者伪造用户请求,利用用户的身份进行恶意操作。
    • 解决方案 :设置 SameSite 属性,限制Cookie在跨站请求中的发送行为。使用CSRF令牌来验证请求的合法性。
  3. 会话劫持

    • 描述:攻击者截获用户会话信息,冒充合法用户进行操作。
    • 解决方案 :设置 Secure 属性,确保Cookie只能通过HTTPS连接传输,防止在未加密的连接中被截获。使用强加密的会话令牌,并定期更新。
  4. Cookie欺骗

    • 描述:攻击者伪造Cookie数据,冒充合法用户。
    • 解决方案:对Cookie数据进行签名和加密,防止被篡改和伪造。
  5. Cookie固定攻击(Session Fixation)

    • 描述:攻击者强制用户使用已知的会话ID,随后劫持会话。
    • 解决方案:在用户登录成功后生成新的会话ID,避免会话固定攻击。确保会话ID的复杂性和随机性。

安全解决方案

  1. HttpOnly 属性:

    • 描述:防止客户端脚本(如JavaScript)访问Cookie,从而避免XSS攻击。

    • 示例

      http 复制代码
      Set-Cookie: sessionId=abc123; HttpOnly
  2. Secure 属性:

    • 描述:确保Cookie只能通过HTTPS连接传输,防止在未加密的连接中被截获。

    • 示例

      http 复制代码
      Set-Cookie: sessionId=abc123; Secure
  3. SameSite 属性:

    • 描述:限制Cookie在跨站请求中的发送行为,帮助防止CSRF攻击。

    • 选项

      • Strict:完全禁止跨站请求发送Cookie。
      • Lax:允许部分跨站请求(如GET请求)发送Cookie。
      • None:允许所有跨站请求发送Cookie。
    • 示例

      http 复制代码
      Set-Cookie: sessionId=abc123; SameSite=Strict
  4. 加密和签名

    • 描述:对Cookie数据进行加密和签名,防止被篡改和伪造。
    • 实现:可以使用JWT(JSON Web Token)或其他加密算法来实现。
  5. CSRF令牌

    • 描述:在每个敏感操作的请求中包含一个唯一的CSRF令牌,以验证请求的合法性。

    • 示例 :在表单中包含一个隐藏字段,用于存储CSRF令牌。

      html 复制代码
      <input type="hidden" name="csrf_token" value="unique_token_value">

以下是如何在JavaScript中实现前面提到的Cookie安全措施的示例。我们将使用Express.js作为服务器框架,并在前端使用纯JavaScript来演示如何设置和读取Cookie。

1. 安装和配置Express.js

首先,确保你已经安装了Node.js和npm,然后创建一个新的项目并安装Express和cookie-parser中间件。

bash 复制代码
npm init -y
npm install express cookie-parser

创建一个名为server.js的文件,设置Express服务器并配置Cookie安全措施。

服务器代码(server.js)

javascript 复制代码
const express = require('express');
const cookieParser = require('cookie-parser');

const app = express();
const port = 3000;

// 使用cookie-parser中间件
app.use(cookieParser());

// 设置安全的Cookie
app.get('/set-cookie', (req, res) => {
  res.cookie('sessionId', 'abc123', { 
    maxAge: 900000, 
    httpOnly: true, 
    secure: true, 
    sameSite: 'Strict' 
  });
  res.send('Secure cookie has been set');
});

// 读取Cookie
app.get('/get-cookie', (req, res) => {
  const sessionId = req.cookies.sessionId || 'No session';
  res.send(`Session ID: ${sessionId}`);
});

app.listen(port, () => {
  console.log(`Server is running at http://localhost:${port}`);
});

在这个示例中,我们设置了一个名为sessionId的Cookie,具有以下安全属性:

  • httpOnly: 确保Cookie只能通过服务器端脚本访问。
  • secure: 确保Cookie只能通过HTTPS连接传输。
  • sameSite: 'Strict': 限制Cookie在跨站请求中的发送行为,防止CSRF攻击。

2. 前端代码

在前端,我们可以使用纯JavaScript来设置和读取Cookies。以下是一个示例,展示了如何在前端设置和读取Cookie。

创建一个名为index.html的文件,并编写以下代码:

前端代码(index.html)

html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Cookie Example</title>
</head>
<body>
  <h1>Cookie Example</h1>
  <button onclick="setClientCookie()">Set Client Cookie</button>
  <button onclick="getClientCookie()">Get Client Cookie</button>
  <button onclick="setServerCookie()">Set Server Cookie</button>
  <button onclick="getServerCookie()">Get Server Cookie</button>
  <p id="output"></p>

  <script>
    // 设置客户端Cookie
    function setClientCookie() {
      document.cookie = "clientCookie=javascript_user; max-age=3600; path=/";
      document.getElementById('output').innerText = "Client cookie has been set";
    }

    // 读取客户端Cookie
    function getClientCookie() {
      const cookies = document.cookie.split('; ').reduce((prev, current) => {
        const [name, value] = current.split('=');
        prev[name] = value;
        return prev;
      }, {});
      const clientCookie = cookies.clientCookie || 'No client cookie';
      document.getElementById('output').innerText = `Client Cookie: ${clientCookie}`;
    }

    // 设置服务器端Cookie
    function setServerCookie() {
      fetch('http://localhost:3000/set-cookie', {
        credentials: 'include'
      })
      .then(response => response.text())
      .then(data => {
        document.getElementById('output').innerText = data;
      });
    }

    // 读取服务器端Cookie
    function getServerCookie() {
      fetch('http://localhost:3000/get-cookie', {
        credentials: 'include'
      })
      .then(response => response.text())
      .then(data => {
        document.getElementById('output').innerText = data;
      });
    }
  </script>
</body>
</html>

在这个示例中:

  • setClientCookie 函数设置一个名为clientCookie的客户端Cookie。
  • getClientCookie 函数读取并显示客户端Cookie。
  • setServerCookie 函数向服务器发送请求,设置服务器端的安全Cookie。
  • getServerCookie 函数向服务器发送请求,读取服务器端的Cookie。

Cookie的过期是指当一个Cookie超过其设定的有效期后,浏览器会自动删除该Cookie。以下是Cookie过期过程的详细解释:

设置Cookie的过期时间

  1. Expires 属性

    • Expires 属性指定了Cookie的过期日期和时间。格式通常为UTC时间。

    • 示例

      http 复制代码
      Set-Cookie: sessionId=abc123; Expires=Wed, 21 Oct 2025 07:28:00 GMT
  2. Max-Age 属性

    • Max-Age 属性指定了Cookie的有效期(以秒为单位)。当该时间过去后,Cookie会过期并被删除。

    • 示例

      http 复制代码
      Set-Cookie: sessionId=abc123; Max-Age=3600

Cookie的过期过程

  1. 设置Cookie

    • 当服务器通过Set-Cookie头部设置一个Cookie时,可以指定该Cookie的过期时间或有效期。
    • 浏览器接收到Set-Cookie头部后,会根据指定的ExpiresMax-Age属性来存储Cookie。
  2. Cookie的存储

    • 浏览器会将Cookie存储在本地,并记录其过期时间或剩余的有效期。
  3. 检查过期时间

    • 每次浏览器发送请求时,都会检查已存储的Cookie的有效期。如果Cookie的过期时间已经到达或剩余的有效期已经为0,浏览器将不再发送该Cookie,并从本地存储中删除它。

示例代码

以下是一个示例,展示了如何通过JavaScript设置和检查Cookie的过期时间:

设置Cookie的函数

javascript 复制代码
function setCookie(name, value, expires) {
  let cookieString = `${name}=${value}; path=/`;
  if (expires) {
    cookieString += `; expires=${expires.toUTCString()}`;
  }
  document.cookie = cookieString;
}

// 设置一个有效期为1天的Cookie
const expiryDate = new Date();
expiryDate.setDate(expiryDate.getDate() + 1);
setCookie('username', 'john_doe', expiryDate);

读取和检查Cookie的函数

javascript 复制代码
function getCookie(name) {
  const cookieArray = document.cookie.split('; ');
  for (let i = 0; i < cookieArray.length; i++) {
    const cookiePair = cookieArray[i].split('=');
    if (cookiePair[0] === name) {
      return cookiePair[1];
    }
  }
  return null;
}

// 检查Cookie是否存在
const username = getCookie('username');
if (username) {
  console.log(`Username Cookie: ${username}`);
} else {
  console.log('Username Cookie has expired or does not exist');
}

ExpiresMax-Age 属性可以在不同的上下文中使用,即在HTTP响应头和Cookie设置中。这两个属性虽然有相似的名字,但它们的作用和使用场景有所不同。让我们详细比较它们在HTTP响应头和Cookie设置中的关系和区别:

作用: 控制Cookie的有效期。

  • Expires: 指定Cookie的过期日期和时间。格式通常为UTC时间。

    • 示例

      http 复制代码
      Set-Cookie: sessionId=abc123; Expires=Wed, 21 Oct 2025 07:28:00 GMT
  • Max-Age: 指定Cookie的有效期(以秒为单位)。当该时间过去后,Cookie会过期并被删除。

    • 示例

      http 复制代码
      Set-Cookie: sessionId=abc123; Max-Age=3600

解释:

  • Expires:绝对时间,到达指定日期和时间后,Cookie将失效。
  • Max-Age:相对时间,从设置Cookie的时间开始计时,经过指定的秒数后,Cookie将失效。

HTTP 响应头 的 ExpiresMax-Age 属性

作用: 控制HTTP响应的缓存行为。

  • Expires: 指定资源的过期日期和时间。浏览器在这个时间之前,可以直接从缓存中获取资源,而不需要向服务器发送请求。格式通常为UTC时间。

    • 示例

      http 复制代码
      Expires: Wed, 21 Oct 2025 07:28:00 GMT
  • Cache-Control: max-age: 指定资源的最大缓存时间(以秒为单位)。浏览器在这个时间段内,可以直接从缓存中获取资源,而不需要向服务器发送请求。

    • 示例

      http 复制代码
      Cache-Control: max-age=3600

解释:

  • Expires:绝对时间,到达指定日期和时间后,资源被认为是过期的,需要重新从服务器获取。
  • Cache-Control: max-age:相对时间,从接收到响应的时间开始计时,经过指定的秒数后,资源被认为是过期的,需要重新从服务器获取。

区别和联系

  1. 作用对象不同

    • Cookie的Expires和Max-Age:控制Cookie的有效期,决定浏览器何时删除Cookie。
    • HTTP响应头的Expires和Max-Age:控制资源的缓存行为,决定浏览器何时重新请求资源。
  2. 时间表示方式不同

    • Expires:使用绝对时间(UTC时间)。
    • Max-Age:使用相对时间(以秒为单位)。
  3. 使用场景不同

    • Cookie的Expires和Max-Age:用于设置和管理Cookie的生命周期。
    • HTTP响应头的Expires和Max-Age:用于管理资源的缓存策略,提高网页的加载速度和性能。

示例

设置Cookie过期时间:

http 复制代码
Set-Cookie: username=johndoe; Expires=Wed, 21 Oct 2025 07:28:00 GMT; Path=/
Set-Cookie: sessionId=abc123; Max-Age=3600; Path=/

设置HTTP响应头的缓存策略:

http 复制代码
HTTP/1.1 200 OK
Expires: Wed, 21 Oct 2025 07:28:00 GMT
Cache-Control: max-age=3600
Content-Type: application/json

{ "id": 1, "name": "John Doe" }
相关推荐
萧寂1734 分钟前
vue2使用tailwindcss
前端
明月看潮生20 分钟前
青少年编程与数学 02-006 前端开发框架VUE 04课题、组合式API
前端·javascript·vue.js·青少年编程·编程与数学
她和夏天一样热21 分钟前
【前端系列】Pinia状态管理库
前端·axios·pinia
小彭努力中30 分钟前
57.在 Vue 3 中使用 OpenLayers 点击选择 Feature 设置特定颜色
前端·javascript·vue.js·arcgis·openlayers
JINGWHALE142 分钟前
设计模式 结构型 适配器模式(Adapter Pattern)与 常见技术框架应用 解析
前端·人工智能·后端·设计模式·性能优化·系统架构·适配器模式
DX_水位流量监测1 小时前
水库水雨情监测系统:水位、雨量、流量等参数全天候实时监测
大数据·开发语言·前端·网络·人工智能·信息可视化
autumn8681 小时前
为什么最好吧css的link标签放在head之间?
前端
这个一个非常哈1 小时前
CSS篇之炫酷框
前端·css
轩轩9902181 小时前
正则表达式在JSON里报错
前端·正则表达式·前端框架
晓Ming_1 小时前
SweetAlert2 - 漂亮可定制的 JavaScript 弹窗
前端·javascript