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