# HTTP cookie httponly secure
Date: 2024-11-19


rfc6265中描述

```
4.1.2.6. The HttpOnly Attribute

   The HttpOnly attribute limits the scope of the cookie to HTTP
   requests.  In particular, the attribute instructs the user agent to
   omit the cookie when providing access to cookies via "non-HTTP" APIs
   (such as a web browser API that exposes cookies to scripts).

   Note that the HttpOnly attribute is independent of the Secure
   attribute: a cookie can have both the HttpOnly and the Secure
   attribute.
```

> https://datatracker.ietf.org/doc/html/rfc6265

防止非HTTP的api访问,比如javascript，这部分需要相关客户端（如浏览器）的支持。

```
4.1.2.5. The Secure Attribute

   The Secure attribute limits the scope of the cookie to "secure"
   channels (where "secure" is defined by the user agent).  When a
   cookie has the Secure attribute, the user agent will include the
   cookie in an HTTP request only if the request is transmitted over a
   secure channel (typically HTTP over Transport Layer Security (TLS)
   [
```

[RFC2818](https://datatracker.ietf.org/doc/html/rfc2818)

```
]).

   Although seemingly useful for protecting cookies from active network
   attackers, the Secure attribute protects only the cookie's
   confidentiality.  An active network attacker can overwrite Secure
   cookies from an insecure channel, disrupting their integrity ...
```

指定cookie需要在https环境中使用。

搭建环境使用浏览器验证。

下面是一个完整的 `HttpOnly` 和 `Secure` Cookie 的例子，包括客户端和服务端的实现。我们使用 **Node.js** 和 **Express** 来实现服务端，同时用 **HTML + JavaScript** 模拟客户端的行为。

* * *

### **1\. 服务端：Node.js + Express**

服务端通过设置 `HttpOnly` 和 `Secure` 属性返回 Cookie。为了确保 `Secure` 属性生效，服务端必须运行在 HTTPS 协议下。

#### **安装依赖**

```bash
npm init -y
npm install express
```

#### **代码示例**

创建一个 `server.js` 文件，内容如下：

```javascript
const express = require('express');
const https = require('https');
const fs = require('fs');
const path = require('path');

const app = express();

// 使用 HTTPS（需要 SSL 证书）
const sslOptions = {
key: fs.readFileSync(path.join(__dirname, 'ssl', 'key.pem')),
cert: fs.readFileSync(path.join(__dirname, 'ssl', 'cert.pem')),
};

// 静态文件
app.use(express.static(path.join(__dirname, 'public')));

// 设置带 HttpOnly 和 Secure 的 Cookie
app.get('/set-cookie', (req, res) =&gt; {
res.cookie('session_id', 'abc123', {
httpOnly: true, // 禁止 JavaScript 访问
secure: true, // 仅在 HTTPS 下传输
maxAge: 24 * 60 * 60 * 1000, // 1 天有效期
});
res.send('Cookie 已设置');
});

// 模拟获取 Cookie
app.get('/check-cookie', (req, res) =&gt; {
const cookieHeader = req.headers.cookie || '没有 Cookie';
res.send(`收到的 Cookie: ${cookieHeader}`);
});

// 启动 HTTPS 服务器
https.createServer(sslOptions, app).listen(3000, () =&gt; {
console.log('Server is running on https://0.0.0.0:3000');
});
```

#### **生成自签名证书**

运行以下命令生成 SSL 证书，用于本地 HTTPS 服务：

```bash
openssl req -x509 -newkey rsa:2048 -keyout key.pem -out cert.pem -days 365 -nodes
```

将生成的 `key.pem` 和 `cert.pem` 放在 `ssl/` 文件夹中。

* * *

### **2\. 客户端：HTML + JavaScript**

创建一个 `public/index.html` 文件，用于测试服务端的 Cookie。

#### **代码示例**

```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>HttpOnly & Secure Cookie</title>
</head>
<body>
<h1>HttpOnly & Secure Cookie 示例</h1>

<button onclick="setCookie()">设置 Cookie</button>
<button onclick="checkCookie()">检查 Cookie</button>

<p id="result"></p>

<script>
// 设置 Cookie
function setCookie() {
fetch('/set-cookie', { method: 'GET', credentials: 'include' })
.then(response => response.text())
.then(data => {
document.getElementById('result').innerText = data;
});
}

// 检查 Cookie
function checkCookie() {
fetch('/check-cookie', { method: 'GET', credentials: 'include' })
.then(response => response.text())
.then(data => {
document.getElementById('result').innerText = data;
});
}

// 尝试访问 HttpOnly 的 Cookie
console.log('尝试访问 document.cookie:', document.cookie);
</script>
</body>
</html>
```

* * *

### **3\. 测试步骤**

#### **3.1 启动服务端**

运行以下命令启动 HTTPS 服务器：

```bash
node server.js
```

#### **3.2 访问客户端**

在浏览器中打开：

```
https://{ip}:3000
```

#### **3.3 测试功能**

**1.设置 Cookie**： - 点击 "设置 Cookie" 按钮，服务端将返回一个带有 `HttpOnly` 和 `Secure` 属性的 Cookie。

**2.检查 Cookie**： - 点击 "检查 Cookie" 按钮，服务端会解析请求头中的 Cookie 并返回给客户端显示。

**3.验证 `HttpOnly`**： - 打开浏览器的开发者工具，在控制台输入：

```javascript
console.log(document.cookie);
```

输出中不会显示 `HttpOnly` 的 `session_id`，因为 JavaScript 无法访问它， 相反如果将server.js代码的httponly设置成false，就可以访问了。

1. **验证 `Secure`**：

\- 将服务器切换到 HTTP 协议（移除 HTTPS 配置），再次访问，会发现 `session_id` 不会被传递，因为浏览器强制要求 `Secure` Cookie 只能通过 HTTPS 传输。

* * *

### **4\. 关键点总结**

**1\. HttpOnly**： - 防止 JavaScript 访问 Cookie，减少 XSS 攻击的风险。 - 浏览器控制台的 `document.cookie` 无法显示带有 `HttpOnly` 的 Cookie。

**2\. Secure**： - 确保 Cookie 只能在 HTTPS 环境中传输，防止中间人攻击窃取 Cookie。 - 在 HTTP 环境下，`Secure` 的 Cookie 不会被浏览器发送。

**3\. 跨域支持**： - 在跨域请求时，需添加 `credentials: 'include'` 以确保 Cookie 被正确发送。

 

关于httponly，secure OWASP网站上两篇文章。

https://owasp.org/www-community/HttpOnly

https://owasp.org/www-community/controls/SecureCookieAttribute

图片from[湯建雄](https://www.facebook.com/groups/474930279315210/user/100000308203064/?__cft__[0]=AZX9_uUOSXgM81vDcs9nC7VXDB3dCdGvPYdERHpet11R48X2D3OkLaMPuhdbpuZL-qrF_oq-FX3M1tB3DpRcsn3yXg_gqxLE7nsG_sr7Dv2eLApzmh0Xj5kua_89cvaomnSIx70cZvuNhF-1YH4P-shlOcePyHJ4_MXlR6oeio3f4rIIDN82O-ureD4n3OPrjO5wRDOfGKIg01BroFcr5Ozn&__tn__=-UC*F)

