在这里插入图片描述

一、业务背景:跨应用智能体传统互通安全痛点

鸿蒙7 API26 基于AgentExtensionAbility提供原生端侧A2A(Agent-to-Agent)跨应用通信框架,解决政企多应用协同、第三方技能互通四大安全与开发难题:

  1. 无标准化鉴权,任意应用均可调用智能体
    旧方案无统一校验入口,第三方恶意应用可随意连接本地Agent,读取隐私技能数据(管理员密码、病历、政务表单);
  2. 缺少调用白名单管控
    无法限定仅指定合作应用访问技能,全部应用无差别放行,不符合等保2.0最小访问权限规范;
  3. 通信无会话隔离、无指令分级拦截
    第三方应用可调用全部技能,无法区分「查询类低风险指令」「修改/删除高风险指令」;
  4. 连接无生命周期管理,内存泄漏、后台保活冲突
    多应用频繁连接/断开AgentExtensionAbility,未做代理销毁、监听解绑,商用7×24小时终端易出现服务卡死。

A2A核心架构角色定义

  • Agent服务端(Server):提供技能的应用,注册AgentExtensionAbility,对外暴露本地离线技能(四则运算、备忘录、设备管控、国密解密);
  • Agent客户端(Client):第三方调用方应用,通过wantAgent.connectAgent建立跨进程通信通道;
  • 鉴权核心入口onAuth:服务端唯一校验节点,获取调用方包名、握手凭证,实现白名单、分级权限拦截;
  • 双向数据通道onData/sendData:客户端下发指令、服务端返回技能执行结果,支持长会话实时交互。

二、工程全量前置配置(服务端+客户端双端)

2.1 通用@kit依赖导入

import {
  AgentExtensionAbility,
  wantAgent,
  common,
  Want
} from '@kit.AbilityKit';
import { hilog } from '@kit.PerformanceAnalysisKit';
import { BusinessError } from '@kit.BasicServicesKit';

const TAG = "A2A_Agent_Security";
const DOMAIN = 0x0017;

2.2 权限声明(两端必须配置互通权限)

module.json5 增加跨智能体交互系统权限:

"requestPermissions": [
  {
    "name": "ohos.permission.INTERACT_WITH_AGENT",
    "reason": "$string:a2a_interact_skill",
    "usedScene": { "abilities": ["EntryAbility"], "when": "always" }
  }
]

2.3 服务端:注册Agent扩展能力(提供技能方)

"extensionAbilities": [
  {
    "name": "AgentExtService",
    "srcEntry": "./ets/agentserver/AgentExtService.ets",
    "type": "agent",
    "exported": true, // 必须true,允许跨应用访问
    "description": "本地离线技能服务,支持第三方A2A调用",
    "metadata": [
      {
        "name": "agent_config",
        "value": "$profile:agent_config.json"
      }
    ]
  }
]

2.4 agent_config.json 智能体基础配置(resources/base/profile)

{
  "agentCards": [
    {
      "agentId": "local_enterprise_agent_001",
      "name": "政企通用工具智能体",
      "version": "1.0.0",
      "capabilities": { "streaming": true },
      "skills": [
        { "id": "skill_calc", "name": "四则运算查询", "risk": "low" },
        { "id": "skill_note_query", "name": "备忘录读取", "risk": "low" },
        { "id": "skill_brightness_set", "name": "屏幕亮度修改", "risk": "high" },
        { "id": "skill_admin_pwd_decrypt", "name": "管理员密码解密", "risk": "high" }
      ]
    }
  ]
}

三、服务端完整实现:白名单鉴权+分级技能权限管控

文件路径:ets/agentserver/AgentExtService.ets
核心四层安全管控:

  1. 应用包名白名单拦截:仅合作企业应用允许连接;
  2. 握手Token二次校验:客户端携带预共享密钥握手;
  3. 技能风险分级拦截:低风险查询放行,高风险操作二次校验;
  4. 会话生命周期管理:连接、断开日志全埋点,防止内存泄漏。
export default class AgentExtService extends AgentExtensionAbility {
  // 1. 可信第三方应用白名单(仅允许这些包名A2A互通)
  private readonly ALLOW_BUNDLE_LIST = [
    "com.enterprise.merchant",
    "com.enterprise.gov.office"
  ];
  // 2. 预共享握手密钥(政企多应用统一分发,生产存入HUKS加密存储)
  private readonly SHARED_HANDSHAKE_TOKEN = "A2A_ENTERPRISE_2026_SECURE";
  // 高风险技能黑名单,普通第三方禁止调用
  private readonly HIGH_RISK_SKILL = ["skill_brightness_set", "skill_admin_pwd_decrypt"];

  onCreate(): void {
    hilog.info(DOMAIN, TAG, "A2A跨应用智能体服务启动就绪");
  }

  /**
   * A2A核心鉴权入口:客户端发起连接时强制校验
   * proxy:通信代理对象,可获取调用方信息、授权/拒绝连接
   * handshakeData:客户端携带的握手凭证(预共享Token)
   */
  onAuth(proxy: common.AgentHostProxy, handshakeData: string): void {
    // 步骤1:获取发起调用的第三方应用包名
    const callerBundle = proxy.getCallerBundleName();
    hilog.info(DOMAIN, TAG, `收到A2A连接请求,调用方应用:${callerBundle}`);

    // 校验1:应用包名不在白名单,直接拒绝连接
    if (!this.ALLOW_BUNDLE_LIST.includes(callerBundle)) {
      proxy.authorize("deny:bundle_not_allow");
      hilog.warn(DOMAIN, TAG, `非法应用${callerBundle}被拦截,禁止A2A访问`);
      return;
    }

    // 校验2:握手Token不匹配,拒绝连接
    if (handshakeData !== this.SHARED_HANDSHAKE_TOKEN) {
      proxy.authorize("deny:token_invalid");
      hilog.warn(DOMAIN, TAG, `应用${callerBundle}握手密钥错误,连接拒绝`);
      return;
    }

    // 双重校验通过,授予连接权限
    proxy.authorize("success");
    hilog.info(DOMAIN, TAG, `可信应用${callerBundle}鉴权成功,建立A2A通信会话`);
  }

  /**
   * 接收第三方客户端下发指令,执行技能并分级权限拦截
   */
  onData(proxy: common.AgentHostProxy, inputRaw: string): void {
    const callerBundle = proxy.getCallerBundleName();
    let req;
    try {
      req = JSON.parse(inputRaw);
    } catch {
      proxy.sendData(JSON.stringify({ code: -1, msg: "指令格式错误" }));
      return;
    }

    const skillId = req.skillId;
    const params = req.params;
    hilog.info(DOMAIN, TAG, `A2A调用:应用${callerBundle} 请求技能${skillId}`);

    // 分级权限拦截:高风险技能直接拒绝第三方调用
    if (this.HIGH_RISK_SKILL.includes(skillId)) {
      const res = JSON.stringify({
        code: 403,
        msg: "权限不足:第三方应用禁止调用高风险修改类技能"
      });
      proxy.sendData(res);
      return;
    }

    // 分发低风险技能执行
    const skillResult = this.dispatchSafeSkill(skillId, params);
    proxy.sendData(JSON.stringify({ code: 0, data: skillResult }));
  }

  /** 低风险安全技能执行逻辑 */
  private dispatchSafeSkill(skillId: string, params: Record<string, string>): string {
    switch (skillId) {
      case "skill_calc": {
        const expr = params.expr.replace(/[^0-9\+\-\*\/\.]/g, "");
        return `计算结果:${eval(expr)}`;
      }
      case "skill_note_query": {
        return "备忘录列表:1.鸿蒙A2A跨应用智能体开发 2.商用Kiosk锁机配置";
      }
      default:
        return "未识别的安全技能ID";
    }
  }

  onDestroy(): void {
    hilog.info(DOMAIN, TAG, "A2A智能体服务销毁,释放全部通信代理");
  }
}

四、客户端完整实现:第三方应用发起A2A跨应用调用

第三方合作应用页面,携带握手Token建立跨应用连接,下发标准化技能指令,接收服务端返回结果。
在这里插入图片描述

import { ComponentV2, Local } from '@kit.ArkUI';
import { wantAgent, common, Want } from '@kit.AbilityKit';
import { hilog } from '@kit.PerformanceAnalysisKit';

const TAG = "A2A_Client_Demo";
// 服务端应用包名、Agent扩展Ability名称
const SERVER_BUNDLE = "com.enterprise.agent.server";
const SERVER_AGENT_ABILITY = "AgentExtService";
// 与服务端统一的握手凭证
const HANDSHAKE_TOKEN = "A2A_ENTERPRISE_2026_SECURE";

@Entry
@ComponentV2
struct A2AClientPage {
  @Local inputSkillId: string = "skill_calc";
  @Local inputParam: string = "123*45";
  @Local receiveMsg: string = "未连接跨应用智能体";
  private agentProxy: common.AgentHostProxy | null = null;
  private targetWant: Want = {
    bundleName: SERVER_BUNDLE,
    abilityName: SERVER_AGENT_ABILITY
  };

  aboutToDisappear() {
    // 页面销毁强制断开A2A会话,释放通信句柄
    this.disconnectAgent();
  }

  /** 建立A2A跨应用连接,握手鉴权 */
  async connectRemoteAgent() {
    try {
      this.agentProxy = await wantAgent.connectAgent(this.targetWant, {
        // 握手数据,服务端onAuth接收校验
        handshakeData: HANDSHAKE_TOKEN,
        onConnect: (proxy) => {
          this.receiveMsg = "A2A跨应用智能体连接成功,可下发技能指令";
          // 监听服务端返回的技能执行结果
          proxy.on("data", (msg: string) => {
            this.receiveMsg = `服务端返回结果:\n${msg}`;
          });
        },
        onDisconnect: () => {
          this.agentProxy = null;
          this.receiveMsg = "A2A跨应用会话已断开";
        }
      });
    } catch (err) {
      const e = err as BusinessError;
      this.receiveMsg = `A2A连接失败:${e.code} ${e.message}`;
      hilog.error(0x0017, TAG, `跨应用Agent连接异常:${JSON.stringify(err)}`);
    }
  }

  /** 下发标准化技能指令给远端应用智能体 */
  sendSkillCommand() {
    if (!this.agentProxy || !this.inputSkillId.trim()) return;
    // 标准化请求报文
    const sendBody = JSON.stringify({
      skillId: this.inputSkillId,
      params: { expr: this.inputParam }
    });
    this.agentProxy.sendData(sendBody);
  }

  /** 断开A2A跨应用通信会话 */
  disconnectAgent() {
    if (this.agentProxy) {
      wantAgent.disconnectAgent(this.agentProxy);
      this.agentProxy = null;
    }
  }

  build() {
    Column({ space: 20 }) {
      Text("A2A跨应用智能体|第三方客户端调用演示")
        .fontSize(22)
        .fontWeight(FontWeight.Bold)
        .margin({ top: 20 });

      Text(this.receiveMsg)
        .width("90%")
        .padding(16)
        .backgroundColor("#F0F7FF")
        .borderRadius(12)
        .fontSize(14)
        .whiteSpace(WhiteSpace.PreWrap);

      Column({ space: 12 }) {
        Row({ space: 10 }) {
          Text("技能ID:").width(80);
          TextInput({ text: this.inputSkillId })
            .layoutWeight(1)
            .onChange(v => this.inputSkillId = v);
        }
        Row({ space: 10 }) {
          Text("参数:").width(80);
          TextInput({ text: this.inputParam })
            .layoutWeight(1)
            .onChange(v => this.inputParam = v);
        }
      }
      .width("90%");

      Flex({ wrap: FlexWrap.Wrap, gap: 10 }) {
        Button("1.连接远端第三方智能体").onClick(() => this.connectRemoteAgent());
        Button("2.下发技能指令").backgroundColor("#0A59F7").onClick(() => this.sendSkillCommand());
        Button("3.断开A2A会话").backgroundColor("#888").onClick(() => this.disconnectAgent());
      }
      .width("90%");

      Text("可用安全技能:skill_calc、skill_note_query;高风险技能第三方禁止调用")
        .fontSize(12)
        .fontColor("#888")
        .margin({ top: 10 });

      Blank();
      Text("💡 四层安全管控:白名单应用校验+握手Token+技能分级拦截+会话生命周期销毁")
        .fontSize(12)
        .fontColor("#AAAAAA")
        .margin({ bottom: 30 });
    }
    .width("100%")
    .height("100%")
    .padding({ left: 16, right: 16 })
    .backgroundColor("#F8F9FA");
  }
}

五、进阶安全加固方案(政企商用必做)

5.1 握手Token存入HUKS硬件密钥托管,禁止硬编码

使用SecurityKit HUKS生成对称密钥,握手Token从TEE安全区读取,杜绝逆向抓取密钥:

// 伪代码:从HUKS读取预共享握手凭证
async function getA2AHandshakeToken(): Promise<string> {
  const tokenRaw = await huks.getData("a2a_handshake_key");
  return new TextDecoder().decode(tokenRaw);
}

5.2 高风险技能增加用户二次弹窗授权

修改密码、文件删除、硬件管控等高风险指令,即使在白名单内,也需要本地用户弹窗确认后再执行。

5.3 多应用动态白名单(MDM远程下发)

政企批量终端搭配HEM设备管理平台,远程更新ALLOW_BUNDLE_LIST白名单,无需重新打包应用。

5.4 A2A通信报文SM3哈希完整性校验

客户端发送指令携带SM3摘要,服务端校验报文未被篡改,防止中间人篡改指令越权操作:

// 客户端发送报文附加hash
const raw = JSON.stringify(body);
const hash = cryptoFramework.createMd("SM3").update(raw).digest();
const sendPack = { data: raw, sign: btoa(hash) };

5.5 会话超时自动断开

设置5分钟无通信自动断开agentProxy,防止长期闲置会话被恶意劫持。

六、高频商用开发踩坑完整排坑手册

坑1:connectAgent连接持续失败,返回权限拒绝

  1. 两端module.json5未声明ohos.permission.INTERACT_WITH_AGENT互通权限;
  2. 服务端AgentExtensionAbility未配置exported:true,跨应用不可见;
  3. bundleName、abilityName填写错误,与服务端工程配置不匹配;
  4. 使用调试自动签名,正式企业签名才允许跨应用Agent互通。

坑2:onAuth鉴权不触发,第三方直接连接成功

根因:客户端connectAgent未传入handshakeData参数,系统跳过握手校验;
修复:客户端必须携带握手Token,服务端才能进入onAuth鉴权流程。

坑3:白名单配置失效,陌生应用仍可连接

  1. getCallerBundleName()获取包名大小写不匹配,对比判断失效;
  2. 服务端未做全量字符串匹配,存在模糊匹配漏洞;
    规范:包名全字符严格相等校验,统一小写对比。

坑4:第三方可调用高风险隐私技能,权限拦截失效

根因:技能分级判断写在onData分支末尾,未提前拦截;
规范:进入onData第一时间判断技能风险等级,高风险直接返回403拒绝,不执行业务逻辑。

坑5:页面反复连接Agent,句柄泄漏、服务卡死

解决方案:页面aboutToDisappear强制调用wantAgent.disconnectAgent销毁代理,商用7×24小时终端必须做资源回收。

坑6:模拟器无法调试A2A跨应用通信

模拟器无跨进程Agent路由服务,必须两台真机分别安装客户端、服务端应用,同账号组网测试。

坑7:传输敏感明文数据存在泄露风险

优化:A2A传输前使用HUKS SM4加密报文,跨进程仅传输密文,服务端本地TEE解密后执行技能。

七、政企商用生产级最佳实践

  1. 四层安全标准化流程
    应用白名单校验 → 握手密钥Token校验 → 技能风险分级拦截 → 报文哈希完整性校验,缺一不可;
  2. 最小权限原则
    第三方仅开放查询类低风险技能,修改、解密、硬件管控等高风险技能仅允许自身应用调用;
  3. 全链路操作审计日志
    A2A连接建立/断开、鉴权成功/拒绝、技能调用、指令参数全部打印hilog,安全事件可追溯;
  4. 离线无网络兼容
    A2A端侧通信完全本地进程交互,不依赖云端,适配政务、门店断网自助终端;
  5. 多智能体协同兼容
    A2A可搭配DistributedMultiKit多端同步、Kiosk锁机、本地AgentExtensionAbility技能体系,形成完整政企端侧AI协同方案;
  6. 签名强绑定隔离
    Agent服务与应用签名证书绑定,其他同名包签名不一致无法通过鉴权,防止仿冒应用劫持A2A通道。

八、方案总结

鸿蒙7端侧A2A跨应用智能体通信基于AgentExtensionAbility实现标准化第三方技能互通,依托onAuth统一鉴权入口构建白名单应用管控、握手密钥校验、技能分级权限拦截三层核心安全体系,彻底解决第三方应用随意访问本地隐私技能、越权操作等政企合规痛点。
整套方案纯本地端侧运行、无网络依赖,支持双向长会话实时交互,适配政务多应用协同、零售门店多终端技能互通、企业内部工具联动等商用场景,是鸿蒙跨应用智能体互通的安全标准化落地方案。

Logo

作为“人工智能6S店”的官方数字引擎,为AI开发者与企业提供一个覆盖软硬件全栈、一站式门户。

更多推荐