API Key限额管理
Base URL: https://api.qnaigc.com
概述
用于设置与查询指定 APIKey 的金额限额配置(按日 / 按月 / 总限额),当用量达到限额时将触发限额拦截(返回错误)。
认证方式
本接口仅支持 AK/SK 签名认证:使用七牛云标准的 AK/SK 签名认证。
Authorization: Qiniu <AccessKey>:<EncodedSign>
设置 API KEY 限额
PUT /v1/apikey/quota/:api_key
路径参数:
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
api_key |
string |
是 | APIKey 值 |
请求头:
| 名称 | 类型 | 必填 | 描述 |
|---|---|---|---|
Authorization |
string |
是 | AK/SK 签名,格式为 Qiniu <AccessKey>:<EncodedSign> |
Content-Type |
string |
是 | application/json |
请求体:
{
"daily_quota": {
"enabled": false,
"limit": 0,
"alert_threshold": 0
},
"monthly_quota": {
"enabled": false,
"limit": 0,
"alert_threshold": 0
},
"total_quota": {
"enabled": true,
"limit": 100,
"alert_threshold": 80
}
}
字段说明:
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
daily_quota.enabled |
boolean |
是 | 是否启用日限额 |
daily_quota.limit |
number |
是 | 日限额金额(>= 0) |
daily_quota.alert_threshold |
number |
是 | 日限额告警阈值百分比(0~100) |
monthly_quota.enabled |
boolean |
是 | 是否启用月限额 |
monthly_quota.limit |
number |
是 | 月限额金额(>= 0) |
monthly_quota.alert_threshold |
number |
是 | 月限额告警阈值百分比(0~100) |
total_quota.enabled |
boolean |
是 | 是否启用总限额(无时间范围) |
total_quota.limit |
number |
是 | 总限额金额(>= 0) |
total_quota.alert_threshold |
number |
是 | 总限额告警阈值百分比(0~100) |
请求示例:
curl --location --request PUT "https://api.qnaigc.com/v1/apikey/quota/sk-xx" \
--header "Authorization: Qiniu <AccessKey>:<EncodedSign>" \
--header "Content-Type: application/json" \
--data-raw '{
"daily_quota": {"enabled": false, "limit": 0, "alert_threshold": 0},
"monthly_quota": {"enabled": false, "limit": 0, "alert_threshold": 0},
"total_quota": {"enabled": true, "limit": 100, "alert_threshold": 80}
}'
响应示例(200 OK)
{
"status": true,
"data": {
"daily_quota": {
"enabled": false,
"limit": 0,
"alert_threshold": 0
},
"monthly_quota": {
"enabled": false,
"limit": 0,
"alert_threshold": 0
},
"total_quota": {
"enabled": true,
"limit": 100,
"alert_threshold": 80
},
"created_at": "2006-01-02 15:04:05",
"updated_at": "2006-01-02 15:04:05"
}
}
查询指定 API Key 的限额配置
GET /v1/apikey/quota/:api_key
路径参数:
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
api_key |
string |
是 | APIKey 值 |
请求头:
| 名称 | 类型 | 必填 | 描述 |
|---|---|---|---|
Authorization |
string |
是 | AK/SK 签名,格式为 Qiniu <AccessKey>:<EncodedSign> |
请求示例:
curl --location "https://api.qnaigc.com/v1/apikey/quota/sk-xx" \
--header "Authorization: Qiniu <AccessKey>:<EncodedSign>"
响应示例(200 OK)
{
"status": true,
"data": {
"daily_quota": {
"enabled": true,
"limit": 10,
"alert_threshold": 80
},
"monthly_quota": {
"enabled": true,
"limit": 200,
"alert_threshold": 80
},
"total_quota": {
"enabled": false,
"limit": 0,
"alert_threshold": 0
},
"created_at": "2006-01-02 15:04:05",
"updated_at": "2006-01-02 15:04:05"
}
}
错误状态码
| 状态码 | 说明 |
|---|---|
| 400 | 请求参数错误(如 limit < 0、alert_threshold 不在 0~100) |
| 401 | 认证失败(签名无效) |
| 500 | 服务器内部错误 |
注意事项
api_key支持携带Bearer前缀,例如:Bearer sk-xx。alert_threshold为百分比值(0~100),用于告警阈值配置;是否产生告警取决于服务端告警策略。- 配额配置写入后可能存在短暂延迟才生效(0~30s)。
AK/SK 签名算法
概述
七牛云 API 使用 HMAC-SHA1 签名算法进行身份验证。签名结果附加在请求头的 Authorization 字段中,格式为:
Authorization: Qiniu <AccessKey>:<EncodedSign>
签名生成步骤
1. 生成待签名字符串
待签名字符串由以下部分组成(每部分用换行符分隔):
<Method> <Path>[?Query]
Host: <Host>
Content-Type: <Content-Type>
[X-Qiniu-<HeaderKey>: <HeaderValue>]
<Body>
注意:
Method为 HTTP 方法(如 GET、PUT),大写Path为请求路径,不包含域名和查询参数Query为查询参数(不包含开头的?),仅在有时才添加Host为主机名(如api.qnaigc.com)Content-Type为请求内容类型(如application/json)X-Qiniu-*为可选的自定义头,按 key 的 ASCII 顺序排列,格式化为X-Qiniu-<Key>(每个单词首字母大写)- 待签名串中在 headers 部分结束后,会追加两个连续换行符
\n\n Body为请求体(仅当 Content-Type 不是application/octet-stream时才添加)
2. 计算 HMAC-SHA1 签名
使用 SecretKey 作为密钥,对待签名字符串进行 HMAC-SHA1 运算:
const hmac = crypto.createHmac('sha1', secretKey);
hmac.update(signingStr);
const sign = hmac.digest();
3. Base64 编码
对签名结果进行 URL 安全的 Base64 编码(+ 替换为 -,/ 替换为 _):
function urlSafeBase64Encode(buffer) {
return buffer.toString('base64').replace(/\+/g, '-').replace(/\//g, '_');
}
const encodedSign = urlSafeBase64Encode(sign);
4. 生成最终凭证
将 AccessKey 和 encodedSign 用冒号连接:
<AccessKey>:<EncodedSign>
完整示例代码(Node.js)
下面示例演示:
- GET
/v1/apikey/quota/sk-xx查询限额 - PUT
/v1/apikey/quota/sk-xx设置限额(包含 JSON Body,因此签名需要包含Content-Type和 Body)
const crypto = require('crypto');
/**
* URL 安全的 Base64 编码
*/
function urlSafeBase64Encode(buffer) {
return buffer.toString('base64').replace(/\+/g, '-').replace(/\//g, '_');
}
/**
* 生成待签名的原始字符串
*/
function generateSigningString(options) {
const { method, path, query, host, contentType, headers, body } = options;
let signingStr = method.toUpperCase();
signingStr += ' ' + path;
if (query) {
signingStr += '?' + query;
}
signingStr += '\nHost: ' + host;
if (contentType) {
signingStr += '\nContent-Type: ' + contentType;
}
if (headers) {
const sortedKeys = Object.keys(headers).sort();
sortedKeys.forEach((key) => {
if (key.toLowerCase().startsWith('x-qiniu-')) {
const formattedKey = key
.split('-')
.map((part) => part.charAt(0).toUpperCase() + part.slice(1).toLowerCase())
.join('-');
signingStr += '\n' + formattedKey + ': ' + headers[key];
}
});
}
signingStr += '\n\n';
if (body && contentType && contentType !== 'application/octet-stream') {
signingStr += body;
}
return signingStr;
}
/**
* 生成七牛云管理凭证(Access Token)
*/
function generateAccessToken(accessKey, secretKey, requestOptions) {
const signingStr = generateSigningString(requestOptions);
const hmac = crypto.createHmac('sha1', secretKey);
hmac.update(signingStr);
const sign = hmac.digest();
const encodedSign = urlSafeBase64Encode(sign);
return accessKey + ':' + encodedSign;
}
async function demo() {
const accessKey = '你的 AccessKey';
const secretKey = '你的 SecretKey';
const host = 'api.qnaigc.com';
// 1) GET 查询限额
const getPath = '/v1/apikey/quota/sk-xx';
const getToken = generateAccessToken(accessKey, secretKey, {
method: 'GET',
path: getPath,
host,
});
const getResp = await fetch('https://' + host + getPath, {
headers: { Authorization: 'Qiniu ' + getToken },
});
console.log('GET status:', getResp.status);
console.log(await getResp.text());
// 2) PUT 设置限额
const putPath = '/v1/apikey/quota/sk-xx';
const putBodyObj = {
daily_quota: { enabled: true, limit: 10, alert_threshold: 80 },
monthly_quota: { enabled: true, limit: 200, alert_threshold: 80 },
total_quota: { enabled: false, limit: 1000, alert_threshold: 80 },
};
const putBody = JSON.stringify(putBodyObj);
const putContentType = 'application/json';
const putToken = generateAccessToken(accessKey, secretKey, {
method: 'PUT',
path: putPath,
host,
contentType: putContentType,
body: putBody,
});
const putResp = await fetch('https://' + host + putPath, {
method: 'PUT',
headers: {
Authorization: 'Qiniu ' + putToken,
'Content-Type': putContentType,
},
body: putBody,
});
console.log('PUT status:', putResp.status);
console.log(await putResp.text());
}
demo().catch(console.error);
文档反馈
(如有产品使用问题,请 提交工单)