基于 EdgeOne Edge Function 的 KV 存储管理系统,提供完整的读写删操作接口,支持多命名空间、多种鉴权方式(长期令牌和 TOTP 2FA)。
# 必需: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
# Linux/Mac
openssl rand -base64 32
# Windows (PowerShell)
$bytes = [byte[]]::new(32)
$random = [System.Security.Cryptography.RandomNumberGenerator]::Create()
$random.GetBytes($bytes)
[Convert]::ToBase64String($bytes)
# 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
# 开发环境(使用 .env.local)
wrangler dev --env development
# 生产环境
wrangler deploy --env production
如果你使用 CNB 持续集成发布到 EdgeOne Pages,可按以下步骤配置:
EDGEONE_API_TOKEN.cnb.yml,按注释提示将密钥仓库地址改为你自己的仓库地址。建议:API Token 仅保存在密钥仓库中,不要写入代码或提交到 Git。
.env.example - 配置示例文件(提交到 Git).env.local - 本地开发配置(不提交,由 .gitignore 保护).env - 生产配置(不提交,由 .gitignore 保护)phira_web示例配置:
# .env.local
KV_NAMESPACE_BINDING=phira_web
环境变量: KV_ADMIN_TOKEN
配置示例:
# .env.local
KV_ADMIN_TOKEN=dadwadwadwadwadwa
# 特点:
# - 固定令牌,长期有效
# - 使用简单
# - 需要定期轮换(建议每 90 天)
环境变量: TOTP_SECRET
配置步骤:
.env.local 中配置# .env.local
TOTP_SECRET=dwadwadwadwadwadwadawdwa
# 特点:
# - 每 30 秒变换一次验证码
# - 更加安全
# - 需要认证器应用
# .env.local
KV_ADMIN_TOKEN=ddawdadwadwadwa
TOTP_SECRET=dawdwadwadwadwadwadwadwa
# 好处:
# - 提供多种认证选择
# - 增强安全性
# - 易于令牌轮换
GET /kv-admin/list
查询参数:
prefix (可选) - 键名前缀过滤limit (可选) - 返回数量限制,默认 256,最大 256cursor (可选) - 分页游标响应示例:
{
"complete": true,
"cursor": null,
"keys": [
{"key": "faq"},
{"key": "announcement"},
{"key": "server"}
]
}
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
}
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"
}
DELETE /kv-admin/delete Content-Type: application/json Authorization: Bearer <token> { "key": "test_key" }
响应示例:
{
"success": true,
"message": "Key 'test_key' deleted successfully"
}
| 令牌类型 | 格式 | 有效期 | 来源 |
|---|---|---|---|
| 长期令牌 | 任意字符串 | 长期有效 | KV_ADMIN_TOKEN |
| TOTP码 | 6 位数字 | 90 秒,包含前后空窗期 | TOTP_SECRET |
使用长期令牌:
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"}'
列出所有键:
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"}'
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);
})();
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."
}
{
"error": "Unauthorized",
"message": "Valid admin token required for write operations"
}
{
"error": "Key and value are required"
}
{
"error": "Key not found",
"message": "Key 'test_key' does not exist in KV storage"
}
{
"error": "Method not allowed"
}
| 项目 | 限制 |
|---|---|
| 键名规则 | 只能包含字母、数字和下划线 |
| 键名长度 | 最大 512 字节 |
| 值大小 | 最大 25 MB |
| 分页限制 | 单次最多返回 256 个键 |
| TOTP有效期 | 30 秒,允许前后各 30 秒误差 |
| 读操作鉴权 | 无需鉴权 |
| 写操作鉴权 | 需要令牌鉴权 |
长期令牌安全:
KV_ADMIN_TOKEN(建议每 90 天)TOTP 安全:
原因: KV_NAMESPACE_BINDING 环境变量未配置
解决:
# 复制示例文件
cp .env.example .env.local
# 编辑 .env.local
KV_NAMESPACE_BINDING=xxxxxx
原因: wrangler.toml 中未绑定指定的 KV 命名空间
解决: 在Edgeone Page绑定就好
可能原因:
KV_ADMIN_TOKEN 或 TOTP_SECRET解决步骤:
.env.local 是否配置了认证原因: 通常是服务器时间不同步
解决:
# Linux/Mac
openssl rand -base64 20 | base32 | head -c 32
# 或使用 Python
python3 -c "import os, base64; print(base64.b32encode(os.urandom(20)).decode())"
# 删除 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 | ❌* | Base32 | TOTP 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