logo
1
0
WeChat Login

KV 存储管理 API

基于 EdgeOne Edge Function 的 KV 存储管理系统,提供完整的读写删操作接口,支持多命名空间、多种鉴权方式(长期令牌和 TOTP 2FA)。

目录

1. 快速开始

1.1 前置要求

  • EdgeOne 账户和项目
  • wrangler CLI 工具
  • Node.js 环境

1.2 环境变量配置

参照.env的内容填写完毕添加到Edgeone的环境变量中即可

# 必需:KV 命名空间绑定名(必须与EO KV的命名空间 一致)
KV_NAMESPACE_BINDING=xxxxxx

# 可选:长期管理令牌(用于写操作鉴权)
KV_ADMIN_TOKEN=your_secret_token_here_at_least_32_characters

# 可选:TOTP 2FA 密钥(Base32 编码)
# 注意:至少需要配置上面两个中的一个
TOTP_SECRET=your_totp_secret

1.3 生成安全的令牌和密钥(可跳过)

生成长期令牌

# Linux/Mac
openssl rand -base64 32

# Windows (PowerShell)
$bytes = [byte[]]::new(32)
$random = [System.Security.Cryptography.RandomNumberGenerator]::Create()
$random.GetBytes($bytes)
[Convert]::ToBase64String($bytes)

生成 TOTP 密钥

# Linux/Mac
openssl rand -base64 20 | base32 | head -c 32

# Windows (PowerShell)
$bytes = [byte[]]::new(15)
$random = [System.Security.Cryptography.RandomNumberGenerator]::Create()
$random.GetBytes($bytes)
# 使用在线 Base32 编码工具或以下命令:
# [Convert]::ToBase64String($bytes) | Out-Host

1.4 部署

# 开发环境(使用 .env.local)
wrangler dev --env development

# 生产环境
wrangler deploy --env production

1.5 推送到 EdgeOne Pages(CNB)

如果你使用 CNB 持续集成发布到 EdgeOne Pages,可按以下步骤配置:

  1. 在腾讯云控制台进入 EdgeOne Pages OpenAPI 页面,创建或获取你的 Pages API Token: https://console.cloud.tencent.com/edgeone/pages?tab=api
  2. 在 CNB 创建密钥仓库,并添加密钥:
  • 键名:EDGEONE_API_TOKEN
  • 键值:上一步获取的 Pages API Token
  1. 打开项目根目录下 .cnb.yml,按注释提示将密钥仓库地址改为你自己的仓库地址。
  2. 提交代码并触发流水线,确认 EdgeOne Pages 发布任务执行成功。

建议:API Token 仅保存在密钥仓库中,不要写入代码或提交到 Git。

2. 环境变量详解

2.1 文件位置

  • .env.example - 配置示例文件(提交到 Git)
  • .env.local - 本地开发配置(不提交,由 .gitignore 保护)
  • .env - 生产配置(不提交,由 .gitignore 保护)

2.2 必需配置

2.2.1 KV_NAMESPACE_BINDING (必需)

  • 类型: 字符串
  • 说明: 指定要使用的 KV 命名空间的绑定变量名
  • 示例: phira_web
  • 验证: 必须与 wrangler.toml 中的 binding 名称完全一致
  • 错误处理: 未配置时返回 500 错误并提示配置说明

示例配置:

# .env.local
KV_NAMESPACE_BINDING=phira_web

2.3 鉴权令牌配置(至少配置一个)

2.3.1 方案 A:长期令牌(推荐用于生产环境)

环境变量: KV_ADMIN_TOKEN

  • 类型: 字符串
  • 长度: 至少 32 字符(推荐 64 字符)
  • 说明: 用于写操作(PUT/DELETE)的管理员令牌
  • 生成: 使用强随机数生成器

配置示例:

# .env.local
KV_ADMIN_TOKEN=dadwadwadwadwadwa

# 特点:
# - 固定令牌,长期有效
# - 使用简单
# - 需要定期轮换(建议每 90 天)

2.3.2 方案 B:TOTP 2FA(推荐用于增强安全性)

环境变量: TOTP_SECRET

  • 类型: Base32 编码字符串
  • 长度: 通常 32 字符
  • 说明: 用于生成 TOTP 验证码的密钥
  • 配合: 认证器应用(Google Authenticator、Authy 等)

配置步骤:

  1. 生成 Base32 格式密钥
  2. 在认证器应用中添加密钥(扫描二维码或手动输入)
  3. .env.local 中配置
# .env.local
TOTP_SECRET=dwadwadwadwadwadwadawdwa

# 特点:
# - 每 30 秒变换一次验证码
# - 更加安全
# - 需要认证器应用

2.3.3 方案 C:同时配置两者(最安全)

# .env.local
KV_ADMIN_TOKEN=ddawdadwadwadwa
TOTP_SECRET=dawdwadwadwadwadwadwadwa

# 好处:
# - 提供多种认证选择
# - 增强安全性
# - 易于令牌轮换

3. API 接口

3.1 列出所有键 (无需鉴权)

GET /kv-admin/list

查询参数:

  • prefix (可选) - 键名前缀过滤
  • limit (可选) - 返回数量限制,默认 256,最大 256
  • cursor (可选) - 分页游标

响应示例:

{
  "complete": true,
  "cursor": null,
  "keys": [
    {"key": "faq"},
    {"key": "announcement"},
    {"key": "server"}
  ]
}

3.2 读取键值内容 (无需鉴权)

GET /kv-admin/get?key=test_key&type=text

查询参数:

  • key (必需) - 要读取的键名
  • type (可选) - 返回数据类型
    • text (默认) - 文本格式
    • json - JSON 对象格式
    • arrayBuffer - 二进制数据(返回 base64 编码)
    • stream - 流数据(转换为文本)

响应示例(文本):

{
  "key": "test_key",
  "value": "test_value",
  "type": "text",
  "size": 10
}

响应示例(JSON):

{
  "key": "config",
  "value": {
    "setting1": "value1",
    "setting2": "value2"
  },
  "type": "json",
  "size": 45
}

3.3 写入/更新键值对 (需要鉴权)

PUT /kv-admin/put
Content-Type: application/json
Authorization: Bearer <token>

{
  "key": "test_key",
  "value": "test_value"
}

鉴权方式:

# 方式 1:Authorization Header(推荐)
Authorization: Bearer your_secret_token_here

# 方式 2:Query Parameter
?token=your_secret_token_here

响应示例:

{
  "success": true,
  "message": "Key 'test_key' updated successfully"
}

3.4 删除键值对 (需要鉴权)

DELETE /kv-admin/delete
Content-Type: application/json
Authorization: Bearer <token>

{
  "key": "test_key"
}

响应示例:

{
  "success": true,
  "message": "Key 'test_key' deleted successfully"
}

4. 鉴权详解

4.1 支持的令牌类型

令牌类型格式有效期来源
长期令牌任意字符串长期有效KV_ADMIN_TOKEN
TOTP码6 位数字90 秒,包含前后空窗期TOTP_SECRET

4.2 鉴权示例

使用长期令牌:

curl -X PUT "https://your-domain.com/kv-admin/put" \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer a7f3K9xR2mQ8nB4pL6vJ5wC+D/E=" \
  -d '{"key": "test", "value": "hello"}'

使用 TOTP 验证码(从认证器获取):

curl -X PUT "https://your-domain.com/kv-admin/put" \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer 123456" \
  -d '{"key": "test", "value": "hello"}'

# 或使用查询参数
curl -X PUT "https://your-domain.com/kv-admin/put?token=123456" \
  -H "Content-Type: application/json" \
  -d '{"key": "test", "value": "hello"}'

4.3 认证器应用推荐

  • Google Authenticator (iOS/Android)
  • Microsoft Authenticator (iOS/Android)
  • Authy (iOS/Android/Desktop)
  • 1Password (iOS/Android/Desktop)

5. 使用示例

5.1 curl 命令示例

列出所有键:

curl -X GET "https://your-domain.com/kv-admin/list"

列出前缀为 "config" 的键:

curl -X GET "https://your-domain.com/kv-admin/list?prefix=config&limit=50"

读取单个键值:

curl -X GET "https://your-domain.com/kv-admin/get?key=announcement"

读取 JSON 格式数据:

curl -X GET "https://your-domain.com/kv-admin/get?key=config&type=json"

使用长期令牌创建/更新:

curl -X PUT "https://your-domain.com/kv-admin/put" \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer your_secret_token_here" \
  -d '{"key": "news", "value": "Hello World"}'

使用 TOTP 删除:

curl -X DELETE "https://your-domain.com/kv-admin/delete" \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer 123456" \
  -d '{"key": "old_news"}'

5.2 JavaScript 示例

const API_BASE = 'https://your-domain.com/kv-admin';
const ADMIN_TOKEN = 'your_secret_token_here'; // 或 6 位 TOTP 码

// 列出所有键
async function listKeys(prefix = '', limit = 256) {
  const url = new URL(`${API_BASE}/list`);
  if (prefix) url.searchParams.set('prefix', prefix);
  url.searchParams.set('limit', limit);
  
  const response = await fetch(url);
  return await response.json();
}

// 读取键值
async function getKey(key, type = 'text') {
  const url = new URL(`${API_BASE}/get`);
  url.searchParams.set('key', key);
  url.searchParams.set('type', type);
  
  const response = await fetch(url);
  return await response.json();
}

// 写入/更新键值
async function putKey(key, value, token = ADMIN_TOKEN) {
  const response = await fetch(`${API_BASE}/put`, {
    method: 'PUT',
    headers: {
      'Content-Type': 'application/json',
      'Authorization': `Bearer ${token}`
    },
    body: JSON.stringify({ key, value })
  });
  return await response.json();
}

// 删除键值
async function deleteKey(key, token = ADMIN_TOKEN) {
  const response = await fetch(`${API_BASE}/delete`, {
    method: 'DELETE',
    headers: {
      'Content-Type': 'application/json',
      'Authorization': `Bearer ${token}`
    },
    body: JSON.stringify({ key })
  });
  return await response.json();
}

// 使用示例
(async () => {
  // 列出所有键
  const keys = await listKeys();
  console.log('所有键:', keys);
  
  // 读取特定键
  const data = await getKey('announcement', 'json');
  console.log('公告数据:', data);
  
  // 写入新键
  const result = await putKey('test', 'Hello World');
  console.log('写入结果:', result);
})();

6. 错误响应

500 配置错误

KV 命名空间未配置:

{
  "error": "Configuration error",
  "message": "Environment variable \"KV_NAMESPACE_BINDING\" is not configured. Please set it to the name of your KV namespace binding (e.g., \"phira_web\")"
}

KV 绑定不存在:

{
  "error": "KV namespace not found",
  "message": "KV binding 'phira_web' specified in KV_NAMESPACE_BINDING is not bound in wrangler.toml. Please check your configuration."
}

401 未授权

{
  "error": "Unauthorized",
  "message": "Valid admin token required for write operations"
}

400 请求错误

{
  "error": "Key and value are required"
}

404 键不存在

{
  "error": "Key not found",
  "message": "Key 'test_key' does not exist in KV storage"
}

405 方法不允许

{
  "error": "Method not allowed"
}

7. 限制说明

项目限制
键名规则只能包含字母、数字和下划线
键名长度最大 512 字节
值大小最大 25 MB
分页限制单次最多返回 256 个键
TOTP有效期30 秒,允许前后各 30 秒误差
读操作鉴权无需鉴权
写操作鉴权需要令牌鉴权

8. 安全建议

令牌管理

  1. 长期令牌安全:

    • 使用足够强的随机字符串(至少 32 字符)
    • 定期轮换 KV_ADMIN_TOKEN(建议每 90 天)
    • 不要在代码注释中暴露令牌
    • 限制令牌访问范围(如果可能)
  2. TOTP 安全:

    • 妥善保管生成 TOTP 密钥时的二维码或密钥文本
    • 在认证器应用中启用备份/恢复功能
    • 配置后不要修改密钥(会导致现有验证码失效)
    • 确保服务器时间准确(TOTP 依赖时间同步)

访问控制

  1. 限制管理接口的访问来源(使用 WAF 或网络策略)
  2. 监控写操作日志
  3. 定期审查访问权限
  4. 为不同的服务使用不同的令牌

HTTPS

  • ✅ 生产环境必须使用 HTTPS
  • ❌ 绝不在 HTTP 上传输敏感信息

🚨 常见问题

Q1: 返回 500 "KV namespace not configured"

原因: KV_NAMESPACE_BINDING 环境变量未配置

解决:

# 复制示例文件
cp .env.example .env.local

# 编辑 .env.local
KV_NAMESPACE_BINDING=xxxxxx

Q2: 返回 500 "KV binding not found"

原因: wrangler.toml 中未绑定指定的 KV 命名空间

解决: 在Edgeone Page绑定就好

Q3: 返回 401 未授权

可能原因:

  • 未配置 KV_ADMIN_TOKENTOTP_SECRET
  • 传入的令牌值错误
  • TOTP 验证码已过期(每 30 秒变换一次)
  • 服务器时间不同步(TOTP)

解决步骤:

  1. 检查 .env.local 是否配置了认证
  2. 确认传入的令牌值正确
  3. 对于 TOTP,确认验证码在 30 秒内(允许前后各 30 秒误差)
  4. 同步服务器时钟

Q4: TOTP 验证一直失败

原因: 通常是服务器时间不同步

解决:

  1. 检查服务器时间是否准确
  2. 同步服务器时钟
  3. 检查认证器应用的时间同步

Q5: 如何生成 TOTP 密钥?

# Linux/Mac
openssl rand -base64 20 | base32 | head -c 32

# 或使用 Python
python3 -c "import os, base64; print(base64.b32encode(os.urandom(20)).decode())"

Q6: .env 文件被 Git 提交了怎么办?

# 删除 Git 历史中的 .env 文件(使用 git-filter-repo)
git filter-repo --path .env --invert-paths

# 或添加到 .gitignore 后强制更新
echo ".env" >> .gitignore
git rm --cached .env
git commit -m "Remove .env from tracking"

📊 配置总结表

环境变量必需类型说明
KV_NAMESPACE_BINDING字符串KV 命名空间绑定名
KV_ADMIN_TOKEN❌*字符串长期管理令牌
TOTP_SECRET❌*Base32TOTP 2FA 密钥

* 至少需要配置其中之一用于鉴权

📁 文件结构

KV存储/
├── README.md                          # 本文件
├── .env.example                       # 环境变量示例(提交到 Git)
├── .env.local                         # 本地开发环境(不提交)
├── .gitignore                         # Git 忽略规则(保护 .env 文件)
├── index.html                         # 前端管理界面
├── api/
│   ├── kv/
│   │   └── [key]/
│   │       └── route.ts              # Next.js 开发路由
│   └── kv-admin/
│       └── [action]/
│           └── route.ts              # Next.js 开发路由
└── functions/
    └── api/
        ├── kv/
        │   └── [key].js              # EdgeOne Edge Function
        └── kv-admin/
            └── [action].js           # EdgeOne Edge Function

📚 相关资源

📄 许可证

MIT License

🤝 贡献

欢迎提交 Issue 和 Pull Request!


最后更新: 2026年3月19日

版本: 2.1

About

No description, topics, or website provided.
Language
HTML75.9%
JavaScript24.1%