鸿蒙ArkTS多环境API管理与安全签名方案实践

发布于:2025-07-23 ⋅ 阅读:(15) ⋅ 点赞:(0)

在移动应用开发中,多环境API管理和接口安全是两个核心技术挑战。本文基于真实的鸿蒙项目,深入解析如何构建可扩展的多环境API架构和企业级安全签名体系。

一、技术背景与挑战

业务场景

某项目涉及房源、客源、人员等多个业务域,每个域都有独立的微服务API,且需要在开发、测试、预发布、生产四套环境中无缝切换。

核心挑战

  1. 多域名多环境管理:不同业务模块对应不同服务端口,环境切换复杂
  2. API安全防护:防止接口被恶意调用、参数篡改和重放攻击
  3. 开发效率:环境切换应透明化,不影响业务开发

二、多环境API架构设计

1. 分层架构设计

┌─────────────────────────────────────────┐
│                业务层                    │
│    (CustomerApiService, HouseApiService) │
├─────────────────────────────────────────┤
│             URL管理层 (AppUrl)           │
├─────────────────────────────────────────┤
│           环境配置层 (AppConstant)        │
├─────────────────────────────────────────┤
│          网络请求层 (HttpUtils)          │
└─────────────────────────────────────────┘

2. 环境配置层实现

AppConstant.ets - 环境变量与密钥管理

// 环境控制:true=测试环境,false=生产环境
export const isTest = true

// 环境相关配置
export const EnvConfig = {
  test: {
    apiSecretKey: "",
    mcId: ""
  },
  prod: {
    apiSecretKey: "", 
    mcId: ""
  }
}

// 动态获取当前环境配置
export const getCurrentConfig = () => isTest ? EnvConfig.test : EnvConfig.prod

// 业务域权限标识
export const BusinessDomain = {
  NEW_HOUSE: "sy-xf",    // 新房业务
  TRANSACTION: "qy",      // 交易管理  
  WORKFLOW: "wf",         // 审批流程
  REPORT: "sy-bb"         // 数据报表
} as const

3. URL管理层实现

AppUrl.ets - 多业务域API地址管理

import { isTest } from "../constant/AppConstant"

export class AppUrl {
  // 基础域名配置
  private static readonly BASE_DOMAIN = isTest ? "bbb.t.com" : "bbb.com"
  
  // 业务模块API地址
  static readonly API_ENDPOINTS = {
    // 主业务API
    BASE: `http://${AppUrl.BASE_DOMAIN}/`,
    
    // 客源管理服务
    CUSTOMER: `http://${AppUrl.BASE_DOMAIN}:8011/`,
    
    // 人员管理服务  
    PERSONNEL: `http://${AppUrl.BASE_DOMAIN}:8010/`,
    
    // 房源管理服务
    PROPERTY: `http://${AppUrl.BASE_DOMAIN}:8012/`,
    
    // 公共服务
    COMMON: `http://${AppUrl.BASE_DOMAIN}:8013/`
  } as const

  // 获取完整API地址
  static getApiUrl(endpoint: keyof typeof AppUrl.API_ENDPOINTS, path: string): string {
    return `${AppUrl.API_ENDPOINTS[endpoint]}${path}`
  }
  
  // 环境信息获取
  static getEnvironmentInfo() {
    return {
      environment: isTest ? 'TEST' : 'PRODUCTION',
      domain: AppUrl.BASE_DOMAIN,
      endpoints: AppUrl.API_ENDPOINTS
    }
  }
}

4. 业务服务层调用示例

CustomerApiService.ets - 客源管理API

import { AppUrl } from './AppUrl'

export class CustomerApiService {
  // 获取客源列表
  static getCustomerList(params: any) {
    const url = AppUrl.getApiUrl('CUSTOMER', 'api/customer/list')
    return HttpUtils.get(url, params)
  }
  
  // 添加客源
  static addCustomer(data: any) {
    const url = AppUrl.getApiUrl('CUSTOMER', 'api/customer/add') 
    return HttpUtils.post(url, data)
  }
}

三、企业级安全签名体系

1. 签名算法设计

基于MD5的参数签名算法,防止参数篡改和重放攻击:

AgentUtil.ets - 核心签名实现

import { JSONUtil, LogUtil } from "@pura/harmony-utils"
import { getCurrentConfig } from "../constant/AppConstant"
import { MD5Utils } from "@abner/net"

export class AgentUtil {
  /**
   * 生成ERP系统API安全签名
   * @param paramsJson 请求参数JSON字符串
   * @returns MD5签名字符串
   */
  static getERPSignSecret(paramsJson: string): string {
    try {
      // 1. 参数排序与拼接
      let paramStr = ""
      const paramMap = JSONUtil.jsonToMap(paramsJson)
      
      // 按key排序确保签名一致性
      const sortedKeys = Array.from(paramMap.keys()).sort()
      sortedKeys.forEach(key => {
        const value = paramMap.get(key)
        paramStr += `${key}=${value}&`
      })
      
      // 移除末尾&符号
      paramStr = paramStr.slice(0, -1)
      
      // 2. 构造签名字符串
      const config = getCurrentConfig()
      const signStr = `data${paramStr}secret${config.apiSecretKey}`
      
      LogUtil.info("签名原始字符串", signStr)
      
      // 3. MD5加密
      const signature = MD5Utils.getInstance().hex_md5(signStr)
      
      LogUtil.info("生成签名", signature)
      return signature
      
    } catch (error) {
      LogUtil.error("签名生成失败", error)
      throw new Error("签名生成失败")
    }
  }
  
  /**
   * 验证签名是否有效(客户端预验证)
   * @param params 原始参数
   * @param receivedSign 接收到的签名
   * @returns 是否有效
   */
  static verifySignature(params: any, receivedSign: string): boolean {
    const paramsJson = JSON.stringify(params)
    const expectedSign = AgentUtil.getERPSignSecret(paramsJson)
    return expectedSign === receivedSign
  }
}

2. 网络请求拦截器集成

RequestNetPlugin.ets - 请求签名拦截器

import { AgentUtil } from '../utils/AgentUtil'

export class RequestNetPlugin {
  /**
   * 请求前拦截器:自动添加签名
   */
  static beforeRequest(config: any) {
    // 添加时间戳防重放
    config.data.timestamp = Date.now()
    
    // 生成签名
    const paramsJson = JSON.stringify(config.data)
    const signature = AgentUtil.getERPSignSecret(paramsJson)
    
    // 添加签名到请求参数
    config.data.sign = signature
    
    LogUtil.info("请求签名完成", { url: config.url, sign: signature })
    return config
  }
  
  /**
   * 响应拦截器:验证响应签名(可选)
   */
  static afterResponse(response: any) {
    // 可在此处验证服务端返回的签名
    return response
  }
}

3. 完整请求流程示例

// 业务调用示例
const addCustomer = async (customerData: any) => {
  try {
    // 1. 业务参数
    const params = {
      name: customerData.name,
      phone: customerData.phone,
      requirements: customerData.requirements
    }
    
    // 2. 自动签名(由拦截器处理)
    const response = await CustomerApiService.addCustomer(params)
    
    // 3. 处理响应
    if (response.code === 200) {
      ToastUtil.showToast("客户添加成功")
    }
  } catch (error) {
    LogUtil.error("客户添加失败", error)
  }
}

四、高级特性与优化

1. 环境切换热重载

// 开发期间支持动态切换环境
export class EnvManager {
  static switchEnvironment(env: 'test' | 'prod') {
    // 更新环境标识
    PreferencesUtil.putSync('current_env', env)
    
    // 清理缓存
    this.clearApiCache()
    
    // 重新初始化网络配置
    HttpUtils.reinitialize()
    
    ToastUtil.showToast(`已切换到${env}环境`)
  }
  
  private static clearApiCache() {
    // 清理API响应缓存
  }
}

2. 安全增强策略

export class SecurityUtils {
  // RSA加密敏感参数
  static encryptSensitiveData(data: string): string {
    // RSA加密实现
    return encryptedData
  }
  
  // 请求防重放(基于时间戳和nonce)
  static generateNonce(): string {
    return `${Date.now()}_${Math.random().toString(36)}`
  }
  
  // API限流控制
  static rateLimitCheck(apiPath: string): boolean {
    // 实现API调用频率控制
    return true
  }
}

3. 监控与日志

export class ApiMonitor {
  // API调用统计
  static trackApiCall(url: string, duration: number, success: boolean) {
    const metrics = {
      url,
      duration,
      success,
      timestamp: Date.now(),
      environment: isTest ? 'test' : 'prod'
    }
    
    // 上报到监控系统
    LogUtil.info("API调用监控", metrics)
  }
  
  // 签名失败告警
  static reportSignatureFailure(url: string, params: any) {
    LogUtil.error("签名验证失败", { url, params })
    // 发送告警通知
  }
}

五、最佳实践与注意事项

1. 安全规范

  • 密钥管理:生产环境密钥应通过安全渠道分发,避免硬编码
  • 传输安全:必须配合HTTPS协议使用
  • 签名算法:可根据安全要求升级为HMAC-SHA256或RSA

2. 性能优化

  • 签名缓存:对相同参数的签名结果进行短时缓存
  • 异步处理:签名计算放在工作线程中执行
  • 请求合并:减少不必要的API调用

3. 开发效率

  • 环境一键切换:通过配置中心或构建参数控制环境
  • Mock数据:开发期间可使用Mock服务,减少对后端依赖
  • API文档:维护完整的API文档和签名示例

网站公告

今日签到

点亮在社区的每一天
去签到