帮你快速理解、总结文档立即下载

设置账号 CAM 验证

最近更新时间:2026-08-03 14:55:31
我的收藏
本文为您介绍通过控制台设置账号 CAM 验证相关说明和操作。
说明:
如果您需要开启账号 CAM 验证,请您填写 申请单 申请使用。

支持地域

此功能目前支持的地域为:上海、广州、北京。

背景

在使用消息队列的场景中,通常需要为实例 ACL 创建独立的账号和密码,并授权给相应的用户进行访问和操作。这种方式的账户管理比较复杂,容易出现账号密码泄露等安全问题。基于以上背景,腾讯云消息队列 CKafka 支持为账号启用 CAM 验证功能,通过打通腾讯云平台子账号与 CKafka ACL 账号之间的关系以及增加 CAM 凭证的身份验证,简化账号权限管理的复杂度,提升 CKafka 的安全性和账号管理效率。

操作场景

如果用户对安全性有较高要求,可以通过本功能将 CAM 与 CKafka ACL 账号验证相绑定,用户在请求时可获取对应的密码来访问 CKafka,以提升 CKafka 的安全性。我们建议如下两种场景,启用 CAM 验证。
使用 CAM 身份验证作为临时、个人访问 CKafka 的机制时。
仅对可以轻松重试的工作负载使用 CAM 身份验证。

注意事项

请尽可能使用长连接访问 CKafka,并做好密码重试机制。
启用 CAM 验证前需要提前配置好相关 CAM 权限规则。
启用 CAM 验证后不支持手动修改密码。
关闭 CAM 验证后将无法通过 CAM 获取访问凭证,因此在关闭 CAM 验证时需要输入一个新密码。

功能限制

单个实例内建议不超过 5 个账号开启 CAM 验证。
启用 CAM 验证后不支持对该账号进行重置密码操作。
相同账号名不支持重复启用 CAM 验证功能。

前提条件

已填写 申请单 申请使用此功能。
实例状态为运行中。

步骤1:配置 CAM 权限规则

在使用账号 CAM 验证功能之前,用户需要先配置相关的 CAM 权限规则。

策略内容

{
"statement": [
{
"action": [
"cam:BuildDataFlowAuthToken"
],
"effect": "allow",
"resource": [
"qcs::cam::uin/<用户 uin>:resourceUser/<实例 ID>/<账号名>"
]
}
],
"version": "2.0"
}
<用户 uin>:替换为实际的账号 ID。
<实例 ID>:替换为实际需要授权的实例 ID。
<账号名>:替换为实际需要授权的账号名。

操作指引

1. 使用管理员账号登录访问管理控制台,在 策略 页面,按照策略生成器创建自定义策略(请参见 通过策略生成器创建自定义策略)。

效果:允许
服务:访问管理(cam)
操作:其他操作 - BuildDataFlowAuthToken
资源:特定资源 - 添加资源六段式
填写资源:<实例 ID>/<账号名>
2. 单击下一步,自定义策略的名称,并将策略授予目标子账号。
3. 单击完成,完成授权。

步骤2:启用 CAM 验证

启用 CAM 验证分为两种情形,分别是创建账号时启用 CAM 验证和为已有账号启用 CAM 验证,您可按照如下步骤分别操作。
情形1:创建账号时启用 CAM 验证
情形2:为已有账号启用 CAM 验证
1. 登录 CKafka 控制台
2. 在实例列表,单击实例 ID操作列的管理,进入实例管理页面。
3. 在实例管理页面,选择账号管理 > 创建账号,在弹出的对话框填写相关信息,确认无误后单击确定。
说明:
创建不同权限账号的操作介绍请参考 配置 ACL 用户,以下仅介绍开启 CAM 验证相关的步骤。
启用 CAM 验证:打开“启用 CAM 验证”后的按钮,在弹窗下阅读重要提示后单击确定

1. 登录 CKafka 控制台
2. 在实例列表,单击实例 ID操作列的管理,进入实例管理页面。
3. 在实例管理页面,选择账号管理
4. 在账号管理页面,找到目标账号,在其操作列单击启用 CAM 验证
5. 在弹窗下阅读重要提示后,单击提交


步骤3:在应用程序通过代码调用获取密码

账号具备了相关 CAM 权限规则,并且启用了 CAM 验证后,用户可在应用程序通过 Java 等代码调用来获取密码,从而连接 CKafka 实例。
1. 在腾讯云控制台,账号信息 页面,查询账号的 APPID。

2. 访问管理控制台 > API 密钥管理 获取 SecretID 和 SecretKey。
3. 在应用程序使用如下代码。
<dependency>
<groupId>com.tencentcloudapi</groupId>
<artifactId>tencentcloud-dbauth-sdk-java</artifactId>
<version>1.0.4</version>
</dependency>
间接依赖项:tencentcloud-sdk-java 3.1.1039版本及以上。
<dependency>
<groupId>com.tencentcloudapi</groupId>
<artifactId>tencentcloud-sdk-java</artifactId>
<version>3.1.1039</version>
</dependency>
通过代码调用获取密码的示例
import com.tencentcloudapi.common.Credential;
import com.tencentcloud.dbauth.DBAuthentication;
import com.tencentcloud.dbauth.model.GenerateAuthenticationTokenRequest;
import com.tencentcloudapi.common.exception.TencentCloudSDKException;
import com.tencentcloudapi.common.profile.ClientProfile;
import com.tencentcloudapi.common.profile.HttpProfile;

public class CamTokenHelper {

/**
* 通过腾讯云 CAM 认证获取 Kafka SASL 密码
*
* @param region 实例所在地域,如 ap-guangzhou
* @param instanceId CKafka 实例 ID,如 ckafka-xxxxx
* @param userName SASL 用户名
* @param credential 腾讯云凭证(SecretId + SecretKey)
* @return 认证 Token(用作 SASL 密码)
*/
public static String getAuthToken(String region, String instanceId,
String userName, Credential credential) {
try {
// 实例化 HTTP 选项
HttpProfile httpProfile = new HttpProfile();
httpProfile.setEndpoint("cam.tencentcloudapi.com");

// 实例化 Client 选项
ClientProfile clientProfile = new ClientProfile();
clientProfile.setHttpProfile(httpProfile);

// 构建 GenerateAuthenticationTokenRequest
GenerateAuthenticationTokenRequest tokenRequest =
GenerateAuthenticationTokenRequest.builder()
.region(region)
.credential(credential)
.userName(instanceId + "_" + userName)
.instanceId(instanceId)
.clientProfile(clientProfile)
.build();

// 获取认证 Token
String token = DBAuthentication.generateAuthenticationToken(tokenRequest);
return token;

} catch (TencentCloudSDKException e) {
System.err.println("CAM 认证获取 Token 失败: " + e.getMessage());
e.printStackTrace();
}
return "";
}
}

入参说明:
<region>:替换为您需要访问的实例所在地域,示例:ap-guangzhou。
<instanceId>:替换为需要访问的实例 ID。
<userName>:替换为实际登录的账号名。
<credential.SecretId>:替换为从访问管理控制台获取到的 SecretID。
<credential.SecretKey>:替换为从访问管理控制台获取到的 SecretKey。

步骤4:使用身份令牌连接腾讯云消息队列 CKafka

步骤3 中获取到身份令牌 AuthToken 后,即可使用身份令牌连接腾讯云消息队列 CKafka,以下为生产者代码示例:
import org.apache.kafka.clients.CommonClientConfigs;
import org.apache.kafka.clients.producer.*;
import org.apache.kafka.common.config.SaslConfigs;
import org.apache.kafka.common.serialization.StringSerializer;
import com.tencentcloudapi.common.Credential;

import java.time.Duration;
import java.util.Properties;

public class CamProducerExample {

public static void main(String[] args) {
// ====== 配置参数 ======
String bootstrapServers = "your-ckafka-server:9092"; // CKafka 接入点
String topic = "your-topic"; // Topic 名称
String saslMechanism = "SCRAM-SHA-256"; // SASL 机制
String username = "your-username"; // SASL 用户名
String region = "ap-guangzhou"; // 实例所在地域
String instanceId = "ckafka-xxxxx"; // CKafka 实例 ID

// 腾讯云凭证(建议通过环境变量获取)
String secretId = System.getenv("TENCENTCLOUD_SECRET_ID");
String secretKey = System.getenv("TENCENTCLOUD_SECRET_KEY");
Credential credential = new Credential(secretId, secretKey);

// ====== 通过 CAM 获取 Token 作为密码 ======
String password = CamTokenHelper.getAuthToken(region, instanceId, username, credential);
if (password.isEmpty()) {
System.err.println("获取 CAM Token 失败,退出");
return;
}

// ====== 构建 Kafka Producer 配置 ======
Properties config = new Properties();
config.put(CommonClientConfigs.BOOTSTRAP_SERVERS_CONFIG, bootstrapServers);
config.put(CommonClientConfigs.SECURITY_PROTOCOL_CONFIG, "SASL_PLAINTEXT");
config.put(SaslConfigs.SASL_MECHANISM, saslMechanism);
config.put(SaslConfigs.SASL_JAAS_CONFIG, String.format(
"org.apache.kafka.common.security.scram.ScramLoginModule required username=\\"%s\\" password=\\"%s\\";",
username, password));
config.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, StringSerializer.class.getName());
config.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, StringSerializer.class.getName());

// ====== 发送消息 ======
try (KafkaProducer<String, String> producer = new KafkaProducer<>(config)) {
ProducerRecord<String, String> record = new ProducerRecord<>(topic, "测试消息-" + System.currentTimeMillis());
RecordMetadata metadata = producer.send(record).get();
System.out.printf("消息发送成功: topic=%s, partition=%d, offset=%d%n",
metadata.topic(), metadata.partition(), metadata.offset());
} catch (Exception e) {
System.err.println("发送消息失败: " + e.getMessage());
e.printStackTrace();
}
}
}

<bootstrapServers>:替换为您实际需要访问的 CKafka 接入点
<topic>:替换为您实际需要访问的实例 topic
<saslMechanism>:替换为您实际配置的 SASL 机制(推荐 SCRAM)
<username>:替换为您实际需要访问实例的 ACL 用户名
<groupId>:替换为您实际需要访问实例的消费组 ID
<region>:替换为您实际需要访问实例的所在 region
<instanceId>:替换为您实际需要访问实例的 ID
以下为消费者代码示例:
import org.apache.kafka.clients.CommonClientConfigs;
import org.apache.kafka.clients.consumer.*;
import org.apache.kafka.common.config.SaslConfigs;
import org.apache.kafka.common.serialization.StringDeserializer;
import com.tencentcloudapi.common.Credential;

import java.time.Duration;
import java.util.Arrays;
import java.util.Properties;

public class CamConsumerExample {

public static void main(String[] args) {
// ====== 配置参数 ======
String bootstrapServers = "your-ckafka-server:9092"; // CKafka 接入点
String topic = "your-topic"; // Topic 名称
String saslMechanism = "SCRAM-SHA-256"; // SASL 机制
String username = "your-username"; // SASL 用户名
String groupId = "your-consumer-group"; // 消费者组 ID
String region = "ap-guangzhou"; // 实例所在地域
String instanceId = "ckafka-xxxxx"; // CKafka 实例 ID

// 腾讯云凭证(建议通过环境变量获取)
String secretId = System.getenv("TENCENTCLOUD_SECRET_ID");
String secretKey = System.getenv("TENCENTCLOUD_SECRET_KEY");
Credential credential = new Credential(secretId, secretKey);

// ====== 通过 CAM 获取 Token 作为密码 ======
String password = CamTokenHelper.getAuthToken(region, instanceId, username, credential);
if (password.isEmpty()) {
System.err.println("获取 CAM Token 失败,退出");
return;
}

// ====== 构建 Kafka Consumer 配置 ======
Properties config = new Properties();
config.put(CommonClientConfigs.BOOTSTRAP_SERVERS_CONFIG, bootstrapServers);
config.put(CommonClientConfigs.SECURITY_PROTOCOL_CONFIG, "SASL_PLAINTEXT");
config.put(SaslConfigs.SASL_MECHANISM, saslMechanism);
config.put(SaslConfigs.SASL_JAAS_CONFIG, String.format(
"org.apache.kafka.common.security.scram.ScramLoginModule required username=\\"%s\\" password=\\"%s\\";",
username, password));
config.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class.getName());
config.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class.getName());
config.put(ConsumerConfig.GROUP_ID_CONFIG, groupId);
config.put(ConsumerConfig.AUTO_OFFSET_RESET_CONFIG, "earliest");
config.put(ConsumerConfig.ENABLE_AUTO_COMMIT_CONFIG, "true");

// ====== 消费消息 ======
try (KafkaConsumer<String, String> consumer = new KafkaConsumer<>(config)) {
consumer.subscribe(Arrays.asList(topic));
while (true) {
ConsumerRecords<String, String> records = consumer.poll(Duration.ofMillis(1000));
for (ConsumerRecord<String, String> record : records) {
System.out.printf("收到消息: topic=%s, partition=%d, offset=%d, value=%s%n",
record.topic(), record.partition(), record.offset(), record.value());
}
}
} catch (Exception e) {
System.err.println("消费消息失败: " + e.getMessage());
e.printStackTrace();
}
}
}

<bootstrapServers>:替换为您实际需要访问的 CKafka 接入点
<topic>:替换为您实际需要访问的实例 topic
<saslMechanism>:替换为您实际配置的 SASL 机制(推荐 SCRAM)
<username>:替换为您实际需要访问实例的 ACL 用户名
<groupId>:替换为您实际需要访问实例的消费组 ID
<region>:替换为您实际需要访问实例的所在 region
<instanceId>:替换为您实际需要访问实例的 ID

关闭 CAM 验证

注意:
关闭 CAM 验证后无法通过 CAM 获取访问凭证,请及时更新密码。
1. 登录 CKafka 控制台
2. 在实例列表,单击实例 ID操作列的管理,进入实例管理页面。
3. 在实例管理页面,选择账号管理。
4. 在账号管理页面,找到目标账号,在其操作列单击关闭 CAM 验证
5. 在弹窗下输入新密码并确认密码后单击确定


附录1:错误码

如果返回结果中存在 Error 字段,则表示调用 API 接口失败。有关错误码的说明,请参见 错误码
腾讯云消息队列 CKafka 账号 CAM 验证功能相关的错误码如下:

公共错误码

错误码
说明
AuthFailure.InvalidAuthorization
请求头部的 Authorization 不符合腾讯云标准。
AuthFailure.InvalidSecretId
密钥非法(不是云 API 密钥类型)。
AuthFailure.MFAFailure
MFA 错误。
AuthFailure.SecretIdNotFound
密钥不存在。请在 控制台 检查密钥是否已被删除或者禁用,如状态正常,请检查密钥是否填写正确,注意前后不得有空格。
AuthFailure.SignatureExpire
签名过期。Timestamp 和服务器时间相差不得超过五分钟,请检查本地时间是否和标准时间同步。
AuthFailure.SignatureFailure
签名错误。签名计算错误,请对照调用方式中的签名方法文档检查签名计算过程。
AuthFailure.TokenFailure
token 错误。
AuthFailure.UnauthorizedOperation
请求未授权。请参考 CAM 文档对鉴权的说明。

业务错误码

错误码
说明
FailedOperation.BuildAuthToken
生成 AuthToken 异常。
FailedOperation.FlowAuthIllegal
凭据操作失败。