重置云项目 SecretKey

更新时间:2026-02-09 01:50:42下载pdf

概述

为提升客户账户安全性与运维灵活性,涂鸦开发者平台上线 云项目 SecretKey 重置功能,以帮助您在密钥丢失、泄露或需要轮换时,安全地生成新的 SecretKey,并支持新旧密钥并行使用的过渡期机制,确保业务平稳切换。

当前版本暂不支持已接入 空间智能 SaaS 开发框架 的云项目进行 SecretKey 重置。

适用场景

  • SecretKey 意外泄露或疑似被盗用。
  • 定期安全策略要求轮换密钥。
  • 团队成员变更,需回收旧密钥权限。
  • 运维审计要求密钥定期更新。

功能介绍

支持云项目级 SecretKey 重置

  • ClientID 保持不变,仅 SecretKey 更新。
  • 重置操作由 开发者平台主账号 发起(子账号及菜单授权账号无权限)。

安全过渡期机制

  • 生成新 SecretKey 后,新旧密钥同时生效
  • 默认过渡期:7 天
  • 可自定义调整过渡期时长,最长 30 天
  • 过渡期结束后,旧 SecretKey 自动失效,仅新密钥有效。

严格的操作控制

  • 每个云项目 每天最多申请 2 次 SecretKey 重置。
  • 重置流程 不可撤回
  • 重置过程中(即处于过渡期),禁止再次申请重置

立即失效选项(需二次验证)

  • 如已完成代码/配置更新,可单击 立即失效
  • 系统将 立即停用旧 SecretKey
  • 操作前需 再次验证身份(如短信/邮箱验证码)。

历史记录可追溯

  • 支持查看所有 SecretKey 重置记录(时间、操作人、新旧密钥状态等)。
  • 仅涂鸦开发者平台主账号可见。

使用限制

限制项 说明
账号权限
涂鸦开发者平台主账号 可申请重置和查看记录
SaaS 项目 若云项目下已创建 空间智能 SaaS 实例,则 不支持 SecretKey 重置,单击 重置密钥 按钮时将提示:您当前的云项目已创建空间智能 SaaS,不支持重置密钥
频率限制 每自然日最多支持申请 2 次 重置
流程不可逆 一旦提交重置申请,无法取消或回滚

操作指引

  1. 登录 涂鸦开发者平台

  2. 单击左侧导航栏上的 云开发 > 云项目 > 项目管理 进入 项目管理 页面,然后在目标项目的 操作 栏下单击 进入项目

  3. 授权 > 云授权 下,单击 重置密钥
    重置云项目 SecretKey

  4. 获取并且填写短信/邮件验证码。
    重置云项目 SecretKey

  5. 确认后会生成新 SecretKey,进入 重置中 状态,过渡期默认为7 天
    重置云项目 SecretKey

  6. 支持单击 修改失效时间 设置过渡期时长,在过渡期内新旧密钥同时有效,最长不超过 30 天。
    重置云项目 SecretKey

    重置云项目 SecretKey
  7. 在过渡期内完成代码/服务配置更新。

  8. (可选)如果开启了消息订阅功能,还需要进行 消息解密逻辑变更,详情请参考下方 消息订阅过渡期处理

  9. (可选)更新完成后单击 立即失效 并完成身份验证。

消息订阅过渡期处理

为保证消息订阅的平滑过渡,在 SecretKey 重置过渡期,消息队列发送的消息仍然使用旧密钥加密。在旧密钥失效后,再使用新密钥进行加密。所以需要在代码中增加消息解密的兼容逻辑。

以 Java 为例:
增加 backupAccessKey 参数,配置为待失效的旧密钥。

重置云项目 SecretKey

其次在消息解密处,优先使用新密钥解密,新密钥解密失败则再使用旧密钥加密。

重置云项目 SecretKey

public class ConsumerExample {
    private static final Logger logger = LoggerFactory.getLogger(ConsumerExample.class);

    private static String URL = MqConfigs.WEAZ_SERVER_URL;
    private static String ACCESS_ID = "8scxn*******adyh";
    private static String ACCESS_KEY = "7758*******7b6f";
    private static String ACCESS_KEY_BACKUP = "faaa******6a8b";

    public static void main(String[] args) throws Exception {
        MqConsumer mqConsumer = MqConsumer.build().serviceUrl(URL).accessId(ACCESS_ID).accessKey(ACCESS_KEY)
                .messageListener(message -> {
                    MessageId msgId = message.getMessageId();
                    String encryptModel = message.getProperty(MqConstants.ENCRYPT_MODEL);
                    String payload = new String(message.getData());
                    payloadHandler(payload, encryptModel, msgId);
                });
        mqConsumer.start();
    }

    /**
     * This method is used to process your message business
     */
    private static void payloadHandler(String payload, String encryptModel, MessageId msgId) {
        try {
            MessageVO messageVO = JSON.parseObject(payload, MessageVO.class);
            //decryption data
            String dataJsonStr = "";
            try {
                dataJsonStr = AESBaseDecryptor.decrypt(messageVO.getData(), ACCESS_KEY.substring(8, 24), encryptModel);
            } catch (Exception e) {
                logger.error("###TUYA_PULSAR_MSG => handle payload={},messageId={} your business processing exception, use ACCESS_KEY_BACKUP", payload, msgId);
                if (StringUtils.isNotBlank(ACCESS_KEY_BACKUP)) {
                    dataJsonStr = AESBaseDecryptor.decrypt(messageVO.getData(), ACCESS_KEY_BACKUP.substring(8, 24), encryptModel);
                } else {
                    throw e;
                }
            }

            System.out.println("###TUYA_PULSAR_MSG => decrypt messageVO=" + messageVO + "\n" + "data after decryption dataJsonStr=" + dataJsonStr + " messageId=" + msgId);
        } catch (Exception e) {
            logger.error("###TUYA_PULSAR_MSG => handle payload={},messageId={} your business processing exception, please check and handle.", payload, msgId, e);
        }
    }
}