HarmonyOS开发:安全代码扫描

举报
Jack20 发表于 2026/06/24 16:40:40 2026/06/24
【摘要】 HarmonyOS开发:安全代码扫描📌 核心要点:安全漏洞不是"以后再修"的问题——硬编码密钥、SQL注入、未加密传输,每一个都是等着被利用的定时炸弹。 背景与动机你有没有在代码里写过这种东西?const API_KEY = 'sk-abc123def456'; // 先这么写,上线前再改const DB_PASSWORD = 'admin123'; // 测试环境密码,无所...

HarmonyOS开发:安全代码扫描

📌 核心要点:安全漏洞不是"以后再修"的问题——硬编码密钥、SQL注入、未加密传输,每一个都是等着被利用的定时炸弹。

背景与动机

你有没有在代码里写过这种东西?

const API_KEY = 'sk-abc123def456';  // 先这么写,上线前再改
const DB_PASSWORD = 'admin123';      // 测试环境密码,无所谓

“上线前再改”——这句话你信吗?上线前永远有更紧急的事,密码就这么明晃晃地上了生产环境。然后某天代码仓库泄露了,或者反编译APK就能看到这些字符串,你的系统就裸奔了。

安全漏洞跟普通Bug不一样。普通Bug影响的是用户体验,安全漏洞影响的是用户数据和企业声誉。一个SQL注入漏洞,可能让整个数据库被拖走;一个硬编码密钥,可能让所有加密形同虚设。

鸿蒙应用的安全要求更严格。华为应用市场有安全审核,发现硬编码密钥、未加密传输等问题直接拒绝上架。你辛辛苦苦开发了几个月,因为安全问题被拒,值得吗?

安全扫描的核心价值:在代码合入之前发现安全漏洞,而不是在安全事件之后打补丁

核心原理

安全扫描的检查维度

graph TD
    A[安全代码扫描] --> B[敏感信息泄露]
    A --> C[注入攻击]
    A --> D[数据安全]
    A --> E[通信安全]
    A --> F[权限安全]
    
    B --> B1[硬编码密钥/密码]
    B --> B2[日志打印敏感数据]
    B --> B3[调试信息未清理]
    
    C --> C1[SQL注入]
    C --> C2[命令注入]
    C --> C3[路径遍历]
    
    D --> D1[明文存储敏感数据]
    D --> D2[加密算法不安全]
    D --> D3[密钥管理不当]
    
    E --> E1[HTTP明文传输]
    E --> E2[证书校验缺失]
    E --> E3[中间人攻击风险]
    
    F --> F1[权限过度申请]
    F --> F2[权限绕过]
    F --> F3[敏感操作无鉴权]
    
    classDef mainStyle fill:#FF6B6B,stroke:#C0392B,color:#fff,font-weight:bold
    classDef subStyle fill:#4ECDC4,stroke:#1ABC9C,color:#fff
    classDef detailStyle fill:#FFE66D,stroke:#F39C12,color:#333
    
    class A mainStyle
    class B,C,D,E,F subStyle
    class B1,B2,B3,C1,C2,C3,D1,D2,D3,E1,E2,E3,F1,F2,F3 detailStyle

安全扫描流程

graph LR
    A[源代码] --> B[模式匹配扫描]
    A --> C[数据流分析]
    A --> D[依赖漏洞扫描]
    
    B --> B1[正则匹配敏感信息]
    B --> B2[危险函数调用检测]
    
    C --> C1[污点追踪]
    C --> C2[数据流向分析]
    
    D --> D1[已知CVE检查]
    D --> D2[许可证合规]
    
    B1 --> E[安全报告]
    B2 --> E
    C1 --> E
    C2 --> E
    D1 --> E
    D2 --> E
    
    E --> F{是否通过?}
    F -->|| G[阻断合并/构建]
    F -->|| H[继续流程]
    
    classDef sourceStyle fill:#A8E6CF,stroke:#2ECC71,color:#333
    classDef scanStyle fill:#4ECDC4,stroke:#1ABC9C,color:#fff
    classDef resultStyle fill:#6C5CE7,stroke:#8E44AD,color:#fff
    classDef decisionStyle fill:#FF6B6B,stroke:#E74C3C,color:#fff
    
    class A sourceStyle
    class B,C,D,B1,B2,C1,C2,D1,D2 scanStyle
    class E resultStyle
    class F,G,H decisionStyle

代码实战

基础用法:敏感信息泄露检测

最常见、最危险的安全问题——硬编码敏感信息:

// security-scanner.ts
// 敏感信息泄露检测器

interface SecurityFinding {
  file: string;
  line: number;
  severity: 'critical' | 'high' | 'medium' | 'low';
  category: string;
  ruleId: string;
  description: string;
  recommendation: string;
}

class SensitiveDataScanner {
  private findings: SecurityFinding[] = [];

  // 敏感信息检测规则
  private readonly patterns: Array<{
    name: string;
    pattern: RegExp;
    severity: SecurityFinding['severity'];
    category: string;
    ruleId: string;
  }> = [
    // API密钥
    {
      name: 'API密钥',
      pattern: /(?:api[_-]?key|apikey)\s*[:=]\s*['"][A-Za-z0-9]{20,}['"]/i,
      severity: 'critical',
      category: '敏感信息泄露',
      ruleId: 'SEC-KEY-001',
    },
    // 密码
    {
      name: '密码',
      pattern: /(?:password|passwd|pwd)\s*[:=]\s*['"][^'"]{4,}['"]/i,
      severity: 'critical',
      category: '敏感信息泄露',
      ruleId: 'SEC-KEY-002',
    },
    // Token
    {
      name: '令牌',
      pattern: /(?:token|access[_-]?token|secret)\s*[:=]\s*['"][A-Za-z0-9._-]{20,}['"]/i,
      severity: 'critical',
      category: '敏感信息泄露',
      ruleId: 'SEC-KEY-003',
    },
    // 私钥
    {
      name: '私钥',
      pattern: /-----BEGIN (?:RSA |EC )?PRIVATE KEY-----/,
      severity: 'critical',
      category: '敏感信息泄露',
      ruleId: 'SEC-KEY-004',
    },
    // 数据库连接串
    {
      name: '数据库连接串',
      pattern: /(?:mysql|postgres|mongodb|redis):\/\/[^\s'"]+/i,
      severity: 'high',
      category: '敏感信息泄露',
      ruleId: 'SEC-KEY-005',
    },
    // AWS密钥
    {
      name: 'AWS密钥',
      pattern: /AKIA[0-9A-Z]{16}/,
      severity: 'critical',
      category: '敏感信息泄露',
      ruleId: 'SEC-KEY-006',
    },
  ];

  // 扫描文件
  scanFile(content: string, filePath: string): SecurityFinding[] {
    this.findings = [];
    const lines = content.split('\n');

    lines.forEach((line, index) => {
      for (const rule of this.patterns) {
        if (rule.pattern.test(line)) {
          this.findings.push({
            file: filePath,
            line: index + 1,
            severity: rule.severity,
            category: rule.category,
            ruleId: rule.ruleId,
            description: `检测到硬编码的${rule.name}`,
            recommendation: `${rule.name}移至环境变量或安全存储中`,
          });
        }
      }
    });

    return this.findings;
  }
}

// ==========================================
// 正确做法:使用安全的方式存储敏感信息
// ==========================================

// ❌ 错误:硬编码
const API_KEY_BAD = 'sk-abc123def456';

// ✅ 正确:使用环境变量或安全存储
import { huks } from '@kit.UniversalKeystore';

// 方案1:通过构建配置注入
// build-profile.json5中配置:
// "buildOption": {
//   "arkOptions": {
//     "compilerOptions": {
//       "plugins": [
//         {
//           "name": "env-plugin",
//           "options": {
//             "API_KEY": "$(API_KEY)"  // 从环境变量读取
//           }
//         }
//       ]
//     }
//   }
// }

// 方案2:使用HUKS(通用密钥存储)保护密钥
async function secureKeyManagement(): Promise<void> {
  // 生成密钥别名
  const keyAlias = 'my_api_key';
  
  // 初始化密钥(首次运行时)
  const properties: huks.HuksOptions = {
    properties: [
      { tag: huks.HuksTag.HUKS_TAG_ALGORITHM, value: huks.HuksKeyAlg.HUKS_ALG_AES },
      { tag: huks.HuksTag.HUKS_TAG_KEY_SIZE, value: huks.HuksKeySize.HUKS_AES_KEY_SIZE_256 },
      { tag: huks.HuksTag.HUKS_TAG_PURPOSE, value: huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_ENCRYPT |
                                                    huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_DECRYPT },
      { tag: huks.HuksTag.HUKS_TAG_PADDING, value: huks.HuksKeyPadding.HUKS_PADDING_PKCS7 },
      { tag: huks.HuksTag.HUKS_TAG_BLOCK_MODE, value: huks.HuksCipherMode.HUKS_MODE_CBC },
    ],
    inData: new Uint8Array(0),
  };

  // 生成密钥
  await huks.generateKeyItem(keyAlias, properties);
}

进阶用法:注入攻击检测与数据安全检查

// injection-scanner.ts
// 注入攻击检测器

class InjectionScanner {
  private findings: SecurityFinding[] = [];

  // ==========================================
  // SQL注入检测
  // ==========================================
  checkSqlInjection(content: string, filePath: string): void {
    const lines = content.split('\n');

    lines.forEach((line, index) => {
      // 检测字符串拼接SQL
      const sqlConcatPattern = /(?:SELECT|INSERT|UPDATE|DELETE|DROP).*\+\s*\w+/i;
      if (sqlConcatPattern.test(line)) {
        this.findings.push({
          file: filePath,
          line: index + 1,
          severity: 'critical',
          category: 'SQL注入',
          ruleId: 'SEC-INJ-001',
          description: '检测到字符串拼接SQL,存在SQL注入风险',
          recommendation: '使用参数化查询替代字符串拼接',
        });
      }

      // 检测模板字符串SQL
      const sqlTemplatePattern = /(?:SELECT|INSERT|UPDATE|DELETE|DROP).*\$\{/i;
      if (sqlTemplatePattern.test(line)) {
        this.findings.push({
          file: filePath,
          line: index + 1,
          severity: 'critical',
          category: 'SQL注入',
          ruleId: 'SEC-INJ-002',
          description: '检测到模板字符串拼接SQL,存在SQL注入风险',
          recommendation: '使用参数化查询替代模板字符串',
        });
      }
    });
  }

  // ==========================================
  // 路径遍历检测
  // ==========================================
  checkPathTraversal(content: string, filePath: string): void {
    const lines = content.split('\n');

    lines.forEach((line, index) => {
      // 检测用户输入直接用于文件路径
      const pathTraversalPattern = /(?:open|read|write|delete|stat)\s*\(\s*.*(?:\+|\$\{)/i;
      if (pathTraversalPattern.test(line)) {
        this.findings.push({
          file: filePath,
          line: index + 1,
          severity: 'high',
          category: '路径遍历',
          ruleId: 'SEC-INJ-003',
          description: '用户输入可能直接用于文件路径,存在路径遍历风险',
          recommendation: '对用户输入进行路径校验,禁止包含..和绝对路径',
        });
      }
    });
  }

  // ==========================================
  // 数据安全检查
  // ==========================================
  checkDataSecurity(content: string, filePath: string): void {
    const lines = content.split('\n');

    lines.forEach((line, index) => {
      // 检测Preferences明文存储敏感数据
      const prefsSensitivePattern = /preferences\.(put|set)\s*\(\s*['"]*(?:password|token|key|secret)/i;
      if (prefsSensitivePattern.test(line)) {
        this.findings.push({
          file: filePath,
          line: index + 1,
          severity: 'high',
          category: '数据安全',
          ruleId: 'SEC-DATA-001',
          description: '检测到使用Preferences存储敏感数据,存在明文泄露风险',
          recommendation: '敏感数据应加密后存储,或使用HUKS安全存储',
        });
      }

      // 检测弱加密算法
      const weakCryptoPattern = /(?:DES|RC4|MD5|SHA1)\s*\(/i;
      if (weakCryptoPattern.test(line)) {
        this.findings.push({
          file: filePath,
          line: index + 1,
          severity: 'high',
          category: '数据安全',
          ruleId: 'SEC-DATA-002',
          description: '检测到使用弱加密/哈希算法',
          recommendation: '使用AES-256-GCM替代DES/RC4,使用SHA-256+替代MD5/SHA1',
        });
      }

      // 检测hilog打印敏感数据
      const logSensitivePattern = /hilog\.(info|debug)\s*\([^)]*(?:password|token|key|secret)/i;
      if (logSensitivePattern.test(line)) {
        this.findings.push({
          file: filePath,
          line: index + 1,
          severity: 'medium',
          category: '数据安全',
          ruleId: 'SEC-DATA-003',
          description: '检测到日志中打印敏感数据',
          recommendation: '禁止在日志中输出密码、令牌等敏感信息',
        });
      }
    });
  }

  // ==========================================
  // 通信安全检查
  // ==========================================
  checkCommunicationSecurity(content: string, filePath: string): void {
    const lines = content.split('\n');

    lines.forEach((line, index) => {
      // 检测HTTP明文请求
      const httpPattern = /http:\/\/(?!localhost|127\.0\.0\.1)/i;
      if (httpPattern.test(line)) {
        this.findings.push({
          file: filePath,
          line: index + 1,
          severity: 'high',
          category: '通信安全',
          ruleId: 'SEC-NET-001',
          description: '检测到HTTP明文请求,数据可能被窃听',
          recommendation: '使用HTTPS加密传输,禁止HTTP明文通信',
        });
      }

      // 检测证书校验绕过
      const certBypassPattern = /(?:onSslErrorReceive|onCertificateError)\s*\(\s*\)\s*\{/;
      if (certBypassPattern.test(line)) {
        this.findings.push({
          file: filePath,
          line: index + 1,
          severity: 'critical',
          category: '通信安全',
          ruleId: 'SEC-NET-002',
          description: '检测到SSL证书校验回调,可能绕过证书验证',
          recommendation: '不要绕过SSL证书校验,生产环境必须验证证书',
        });
      }
    });
  }

  // 执行所有检查
  scanAll(content: string, filePath: string): SecurityFinding[] {
    this.findings = [];
    this.checkSqlInjection(content, filePath);
    this.checkPathTraversal(content, filePath);
    this.checkDataSecurity(content, filePath);
    this.checkCommunicationSecurity(content, filePath);
    return this.findings;
  }
}

完整示例:鸿蒙安全编码规范与自动化扫描

// harmony-security-audit.ts
// 鸿蒙安全编码规范审计工具

class HarmonySecurityAuditor {
  private allFindings: SecurityFinding[] = [];

  // 鸿蒙特有的安全检查
  checkHarmonySpecificSecurity(content: string, filePath: string): void {
    const lines = content.split('\n');

    lines.forEach((line, index) => {
      // 检查权限声明
      this.checkPermissionUsage(line, filePath, index);
      // 检查数据备份安全
      this.checkBackupSecurity(line, filePath, index);
      // 检查Web组件安全
      this.checkWebSecurity(line, filePath, index);
      // 检查Ability导出安全
      this.checkAbilityExport(line, filePath, index);
    });
  }

  // 检查权限使用
  private checkPermissionUsage(
    line: string, filePath: string, lineIndex: number
  ): void {
    // 检测过度权限申请
    const dangerousPermissions = [
      'ohos.permission.READ_CALENDAR',
      'ohos.permission.READ_CALL_LOG',
      'ohos.permission.READ_CONTACTS',
      'ohos.permission.LOCATION',
      'ohos.permission.CAMERA',
      'ohos.permission.MICROPHONE',
    ];

    for (const perm of dangerousPermissions) {
      if (line.includes(perm)) {
        // 检查是否有对应的权限使用说明
        if (!line.includes('reason')) {
          this.allFindings.push({
            file: filePath,
            line: lineIndex + 1,
            severity: 'medium',
            category: '权限安全',
            ruleId: 'SEC-PERM-001',
            description: `申请了敏感权限${perm}但未提供使用说明`,
            recommendation: '敏感权限必须在module.json5中声明reason',
          });
        }
      }
    }
  }

  // 检查数据备份安全
  private checkBackupSecurity(
    line: string, filePath: string, lineIndex: number
  ): void {
    // 检测备份配置不当
    if (line.includes('allowBackup') && line.includes('true')) {
      this.allFindings.push({
        file: filePath,
        line: lineIndex + 1,
        severity: 'high',
        category: '数据安全',
        ruleId: 'SEC-BACKUP-001',
        description: '应用允许备份,敏感数据可能通过备份泄露',
        recommendation: '包含敏感数据的应用应设置allowBackup为false',
      });
    }
  }

  // 检查Web组件安全
  private checkWebSecurity(
    line: string, filePath: string, lineIndex: number
  ): void {
    // 检测Web组件的fileFromProxyAccessEnabled
    if (line.includes('fileFromProxyAccessEnabled') && line.includes('true')) {
      this.allFindings.push({
        file: filePath,
        line: lineIndex + 1,
        severity: 'high',
        category: 'Web安全',
        ruleId: 'SEC-WEB-001',
        description: 'Web组件允许代理访问文件,可能被恶意网页利用',
        recommendation: '设置fileFromProxyAccessEnabled为false',
      });
    }

    // 检测JavaScript自动执行
    if (line.includes('javaScriptAccess') && line.includes('true')) {
      this.allFindings.push({
        file: filePath,
        line: lineIndex + 1,
        severity: 'medium',
        category: 'Web安全',
        ruleId: 'SEC-WEB-002',
        description: 'Web组件启用了JavaScript,需确保加载的网页可信',
        recommendation: '仅对可信网页启用JavaScript',
      });
    }
  }

  // 检查Ability导出安全
  private checkAbilityExport(
    line: string, filePath: string, lineIndex: number
  ): void {
    // 检测导出的Ability没有权限保护
    if (line.includes('exported') && line.includes('true')) {
      // 检查后续几行是否有权限声明
      this.allFindings.push({
        file: filePath,
        line: lineIndex + 1,
        severity: 'high',
        category: '组件安全',
        ruleId: 'SEC-ABILITY-001',
        description: 'Ability被导出但可能缺少权限保护',
        recommendation: '导出的Ability应添加权限保护,防止被恶意调用',
      });
    }
  }

  // 生成安全审计报告
  generateSecurityReport(): string {
    let report = '╔══════════════════════════════════════════╗\n';
    report +=    '║      安全代码扫描报告                    ║\n';
    report +=    '╚══════════════════════════════════════════╝\n\n';

    // 按严重程度统计
    const critical = this.allFindings.filter(f => f.severity === 'critical');
    const high = this.allFindings.filter(f => f.severity === 'high');
    const medium = this.allFindings.filter(f => f.severity === 'medium');
    const low = this.allFindings.filter(f => f.severity === 'low');

    report += `📊 问题统计\n`;
    report += `   🔴 严重: ${critical.length}\n`;
    report += `   🟠 高危: ${high.length}\n`;
    report += `   🟡 中危: ${medium.length}\n`;
    report += `   🟢 低危: ${low.length}\n\n`;

    // 按类别分组
    const categories = new Map<string, SecurityFinding[]>();
    for (const finding of this.allFindings) {
      if (!categories.has(finding.category)) {
        categories.set(finding.category, []);
      }
      categories.get(finding.category)!.push(finding);
    }

    for (const [category, findings] of categories) {
      report += `📋 ${category} (${findings.length}个)\n`;
      for (const f of findings) {
        const icon = f.severity === 'critical' ? '🔴' :
                     f.severity === 'high' ? '🟠' :
                     f.severity === 'medium' ? '🟡' : '🟢';
        report += `   ${icon} [${f.ruleId}] ${f.file}:${f.line}\n`;
        report += `      ${f.description}\n`;
        report += `      建议: ${f.recommendation}\n`;
      }
      report += '\n';
    }

    // 安全评分
    const score = Math.max(0, 100 - critical.length * 20 - high.length * 10 - 
                           medium.length * 5 - low.length * 2);
    report += `━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n`;
    report += `🔒 安全评分: ${score}/100\n`;

    if (critical.length > 0) {
      report += `🚫 存在严重安全问题,必须修复后才能发布\n`;
    } else if (high.length > 0) {
      report += `⚠️ 存在高危安全问题,强烈建议修复\n`;
    } else {
      report += `✅ 未发现严重安全问题\n`;
    }

    return report;
  }

  // 执行完整扫描
  runFullScan(files: Map<string, string>): string {
    this.allFindings = [];

    const sensitiveScanner = new SensitiveDataScanner();
    const injectionScanner = new InjectionScanner();

    for (const [filePath, content] of files) {
      // 敏感信息扫描
      const sensitiveFindings = sensitiveScanner.scanFile(content, filePath);
      this.allFindings.push(...sensitiveFindings);

      // 注入攻击扫描
      const injectionFindings = injectionScanner.scanAll(content, filePath);
      this.allFindings.push(...injectionFindings);

      // 鸿蒙特有安全检查
      this.checkHarmonySpecificSecurity(content, filePath);
    }

    return this.generateSecurityReport();
  }
}

踩坑与注意事项

坑1:误报太多,团队开始忽视

安全扫描一跑,几百个问题,其中80%是误报。团队看都不看就关掉了。

解决方案

  • 调整规则敏感度:先跑一遍,把误报多的规则调低优先级
  • 白名单机制:确认是误报的可以加入白名单,但必须注释原因
  • 分级处理:critical必须修,high必须review,medium选择性修

坑2:只扫描源代码,忽略配置文件

module.json5里的权限声明、build-profile.json5里的签名配置——这些配置文件也有安全问题,但经常被忽略。

解决方案

  • 扫描范围包括.ets/.ts/.json/.json5文件
  • 特别检查module.json5中的权限声明和导出配置
  • 检查oh-package.json5中的依赖来源

坑3:修复安全问题引入新Bug

修了一个安全漏洞,结果功能挂了。比如把HTTP改成HTTPS,结果服务端不支持HTTPS。

解决方案

  • 安全修复也要走测试流程
  • 优先修复不影响功能的问题(如日志脱敏)
  • 影响功能的修复需要与后端协同

坑4:忽视运行时安全

静态扫描只能发现代码层面的问题,运行时的安全问题(如内存中的敏感数据、进程间通信安全)检测不到。

解决方案

  • 敏感数据用完立即清零
  • 使用HUKS保护密钥,不要在内存中明文保存
  • 进程间通信使用系统提供的IPC安全机制

坑5:安全扫描不进CI

开发阶段不跑安全扫描,上线前才跑一次,发现一堆问题来不及修。

解决方案

  • 安全扫描集成到CI,每次PR都跑
  • Pre-commit钩子检查硬编码密钥
  • 夜间构建跑全量安全扫描

HarmonyOS 6适配说明

HarmonyOS 6在安全扫描方面的改进:

  1. 应用安全审核工具:华为提供了官方的安全审核工具appscanner,可以自动检测鸿蒙应用的常见安全问题,包括硬编码密钥、权限滥用、数据泄露等。

  2. HUKS增强:HarmonyOS 6的HUKS新增了安全密钥导入功能,可以从服务端安全地导入密钥,不需要在客户端代码中出现明文密钥。

  3. 证书钉扎(Certificate Pinning):新增了证书钉扎API,可以防止中间人攻击。不再需要手动实现证书校验逻辑。

  4. 安全编码规范文档:华为发布了官方的鸿蒙安全编码规范,涵盖了数据安全、通信安全、权限管理等各方面,安全扫描规则可以对照这个规范制定。

  5. DevEco Studio安全提示:IDE内置了安全编码提示,编写不安全的代码时会实时提醒。比如写HTTP URL会提示改为HTTPS。

总结

安全漏洞不是小事,一个硬编码密钥可能让整个系统的安全防线崩溃。安全扫描的核心价值是在问题发生之前发现它。

核心要点:

  • 硬编码密钥零容忍:密钥必须走安全存储,代码里不能出现
  • 注入攻击要防范:参数化查询、输入校验、路径检查
  • 数据安全要重视:加密存储、安全传输、日志脱敏
  • 鸿蒙特有安全:权限声明、Ability导出、Web组件安全
  • 安全扫描进CI:不要等到上线前才检查
维度 评分 说明
学习难度 ⭐⭐⭐ 安全知识需要积累,规则配置需要经验
使用频率 ⭐⭐⭐⭐ CI每次构建都跑,日常开发需要关注
重要程度 ⭐⭐⭐⭐⭐ 安全问题可能导致数据泄露,不可忽视
【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。