feat(protocol): enforce X-Fabric-Version negotiation on node registration
This commit is contained in:
7
Fabric.Backend.Center/src/common/version.ts
Normal file
7
Fabric.Backend.Center/src/common/version.ts
Normal file
@@ -0,0 +1,7 @@
|
||||
export const FABRIC_PROTOCOL_VERSION = '1';
|
||||
|
||||
export function normalizeVersion(input?: string): string {
|
||||
if (!input) return FABRIC_PROTOCOL_VERSION;
|
||||
const v = input.trim();
|
||||
return v;
|
||||
}
|
||||
@@ -6,6 +6,7 @@ import {
|
||||
ForbiddenException,
|
||||
Get,
|
||||
Headers,
|
||||
HttpException,
|
||||
NotFoundException,
|
||||
Param,
|
||||
ParseIntPipe,
|
||||
@@ -25,6 +26,7 @@ import {
|
||||
signCanonical,
|
||||
verifyRequestTime,
|
||||
} from '../common/hmac';
|
||||
import { FABRIC_PROTOCOL_VERSION, normalizeVersion } from '../common/version';
|
||||
|
||||
@Controller('nodes')
|
||||
export class NodesController {
|
||||
@@ -40,7 +42,23 @@ export class NodesController {
|
||||
@Headers('x-fabric-signature') signature?: string,
|
||||
@Headers('x-fabric-timestamp') timestamp?: string,
|
||||
@Headers('x-fabric-nonce') nonce?: string,
|
||||
@Headers('x-fabric-version') fabricVersion?: string,
|
||||
) {
|
||||
const requestedVersion = normalizeVersion(fabricVersion);
|
||||
if (requestedVersion !== FABRIC_PROTOCOL_VERSION) {
|
||||
throw new HttpException(
|
||||
{
|
||||
error: {
|
||||
code: 'FABRIC_VERSION_NOT_SUPPORTED',
|
||||
message: `unsupported protocol version: ${requestedVersion}`,
|
||||
retryable: false,
|
||||
},
|
||||
supportedVersion: FABRIC_PROTOCOL_VERSION,
|
||||
},
|
||||
400,
|
||||
);
|
||||
}
|
||||
|
||||
const secret = process.env.CENTER_SHARED_SECRET as string;
|
||||
if (!signature || !timestamp || !nonce || !verifyRequestTime(timestamp)) {
|
||||
throw new ForbiddenException('invalid hmac headers');
|
||||
@@ -88,6 +106,7 @@ export class NodesController {
|
||||
|
||||
return {
|
||||
status: 'accepted',
|
||||
negotiatedVersion: FABRIC_PROTOCOL_VERSION,
|
||||
node: {
|
||||
id: saved.id,
|
||||
nodeId: saved.nodeId,
|
||||
|
||||
@@ -66,7 +66,7 @@
|
||||
- [x] 鉴权方案定稿(node token / HMAC)
|
||||
- [x] 注册握手协议文档化
|
||||
- [x] 错误码与重试策略统一
|
||||
- [ ] 版本协商(`X-Fabric-Version`)
|
||||
- [x] 版本协商(`X-Fabric-Version`)
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
```
|
||||
|
||||
### Required Headers
|
||||
- `X-Fabric-Version`: 协议版本,当前固定为 `1`
|
||||
- `X-Fabric-Timestamp`: ISO8601 UTC 时间(如 `2026-05-12T11:00:00.000Z`)
|
||||
- `X-Fabric-Nonce`: 随机字符串(建议 UUID)
|
||||
- `X-Fabric-Signature`: HMAC-SHA256 十六进制串
|
||||
@@ -84,7 +85,10 @@ signature = HMAC_SHA256_HEX(CENTER_SHARED_SECRET, canonicalString)
|
||||
## 7. 版本协商(预留)
|
||||
当前版本:`v1`
|
||||
|
||||
后续建议在请求头增加:
|
||||
当前实现要求请求头:
|
||||
- `X-Fabric-Version: 1`
|
||||
|
||||
以支持协议平滑升级。
|
||||
若版本不匹配,Center 返回:
|
||||
- `400`
|
||||
- `error.code = FABRIC_VERSION_NOT_SUPPORTED`
|
||||
- `supportedVersion = "1"`
|
||||
|
||||
Reference in New Issue
Block a user