fix(backend): validate digital sync client key header

This commit is contained in:
baiyanyun
2026-06-07 11:33:59 +08:00
parent bf25bc5a47
commit 8ff1c57b83
2 changed files with 23 additions and 1 deletions

View File

@@ -7,7 +7,9 @@ import com.xspaceagi.agent.core.adapter.dto.digital.DigitalEmployeeSyncResponseD
import com.xspaceagi.system.spec.annotation.RequireResource;
import com.xspaceagi.system.spec.dto.ReqResult;
import jakarta.annotation.Resource;
import org.apache.commons.lang3.StringUtils;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
@@ -19,11 +21,30 @@ import static com.xspaceagi.system.spec.enums.ResourceEnum.CONTENT_DIGITAL_EMPLO
@RequestMapping("/api/digital-employee/sync")
public class DigitalEmployeeSyncController {
private static final String CLIENT_KEY_HEADER = "X-Qiming-Client-Key";
@Resource
private DigitalEmployeeSyncApplicationService digitalEmployeeSyncApplicationService;
@RequestMapping(path = "/outbox", method = RequestMethod.POST)
public ReqResult<DigitalEmployeeSyncResponseDto> syncOutbox(@RequestBody DigitalEmployeeSyncRequestDto request) {
public ReqResult<DigitalEmployeeSyncResponseDto> syncOutbox(
@RequestHeader(name = CLIENT_KEY_HEADER, required = false) String headerClientKey,
@RequestBody(required = false) DigitalEmployeeSyncRequestDto request
) {
if (StringUtils.isBlank(headerClientKey)) {
return ReqResult.create("0001", "客户端 Key header 缺失", null);
}
if (request == null) {
request = new DigitalEmployeeSyncRequestDto();
}
String normalizedHeaderClientKey = headerClientKey.trim();
if (StringUtils.isBlank(request.getClientKey())) {
request.setClientKey(normalizedHeaderClientKey);
} else if (!StringUtils.equals(request.getClientKey().trim(), normalizedHeaderClientKey)) {
return ReqResult.create("0001", "客户端 Key header 与请求体不一致", null);
} else {
request.setClientKey(request.getClientKey().trim());
}
return ReqResult.success(digitalEmployeeSyncApplicationService.syncOutbox(request));
}

View File

@@ -466,6 +466,7 @@ window.QimingClawBridge.digital.flushSync()
- 管理端返回格式包含 `acked[]`,每项带 `outbox_id``entity_type``entity_id``remote_id`
- 若管理端只 ack 批次中的部分 item已 ack 的 item 会标记 synced未 ack 的 item 会保留 failed 状态并进入下一轮补偿。
- 当前接口沿用管理端登录态鉴权,客户端必须能读取到客户端 Key 和登录 ticket/token 才会推送;缺少凭据时保持本地 outbox 等待,并在数字员工同步状态条显示缺少项。
- 管理端接收 outbox 时会校验 `X-Qiming-Client-Key`,请求体缺少 `client_key` 时以 header 为准,二者不一致时拒绝写入。
后端最小落点: