You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Cognito认证连接AWS MQTT3 Websocket时连接意外关闭问题排查

问题描述

通过Websocket连接AWS MQTT 3.1.1,采用Cognito身份认证时触发错误:

Caused by: software.amazon.awssdk.crt.mqtt.MqttException: The connection was closed unexpectedly.

相关实现代码如下:

获取GetCredentialsForIdentityResponse的方法

public GetCredentialsForIdentityResponse getCredentialsForIdentity(AuthenticationResultType accessToken, String identityId) {
    try (var client = CognitoIdentityClient.builder()
            .region(Region.of(region))
            .build()) {
        return client.getCredentialsForIdentity(
                GetCredentialsForIdentityRequest.builder()
                        .identityId(identityId)
                        .logins(
                                Map.of(
                                        "cognito-idp.eu-central-1.amazonaws.com/eu-central-1_XGRz3CgoY",
                                        accessToken.idToken()))
                        .build());
    }
}

构建MqttClientConnection的方法

public MqttClientConnection buildConnection(String prefix,
                                            String region,
                                            String clientId,
                                            GetCredentialsForIdentityResponse credentialsForIdentity)  {
    try (var builder = AwsIotMqttConnectionBuilder.newMtlsBuilderFromPath(null, null)) {
        MqttClientConnectionEvents callbacks = new MqttClientConnectionEvents() {
            @Override
            public void onConnectionInterrupted(int errorCode) {
                log.error("Connection interrupted: " + errorCode + ": " + CRT.awsErrorString(errorCode));
            }

            @Override
            public void onConnectionResumed(boolean sessionPresent) {
                log.error("Connection resumed: " + (sessionPresent ? "existing session" : "clean session"));
            }
        };
        return builder.withEndpoint("%s-ats.iot.%s.amazonaws.com".formatted(prefix, region))
                .withWebsockets(true)
                .withConnectionEventCallbacks(callbacks)
                .withWebsocketSigningRegion(region)
                .withClientId(clientId)
                .withWebsocketCredentialsProvider(
                        new StaticCredentialsProvider.StaticCredentialsProviderBuilder()
                                .withAccessKeyId(  credentialsForIdentity.credentials().accessKeyId().getBytes(UTF_8))
                                .withSecretAccessKey(credentialsForIdentity.credentials().secretKey().getBytes(UTF_8))
                                .withSessionToken( credentialsForIdentity.credentials().sessionToken().getBytes(UTF_8))
                                .build())
                .build();
    }
}

错误触发位置

MqttClientConnection connection) throws ExecutionException, InterruptedException {
    try (connection) {
        CompletableFuture<Boolean> connected = connection.connect();
        boolean sessionPresent = connected.get(); // <--- 错误触发位置
    }
}

可能的问题分析

1. 连接构建器初始化错误

你使用了MTLS专用的构建器newMtlsBuilderFromPath(null, null),但实际走Websocket协议,应该用Websocket专属构建器:

// 替换原构建器初始化代码
var builder = AwsIotMqttConnectionBuilder.newWebsocketBuilder();

MTLS构建器会残留证书相关配置,即使后续设置withWebsockets(true),也会导致握手逻辑冲突,引发连接意外关闭。

2. IAM权限缺失

确认Cognito身份池绑定的IAM角色包含以下核心权限:

  • iot:Connect:允许建立MQTT连接
  • iot:Subscribe/iot:Receive(若需订阅主题)
  • iot:Publish(若需发布消息)
    同时检查角色的信任策略是否正确关联Cognito身份池,确保权限策略生效。

3. 端点格式错误

验证prefix参数是否匹配AWS IoT控制台"设置"页面的端点前缀。前缀错误会导致连接到无效地址,服务器直接关闭连接。

4. 凭证传递方式问题

StaticCredentialsProvider支持直接传入字符串,无需转字节数组,编码异常可能导致凭证解析失败:

// 修改为直接传入字符串
new StaticCredentialsProvider.StaticCredentialsProviderBuilder()
        .withAccessKeyId(credentialsForIdentity.credentials().accessKeyId())
        .withSecretAccessKey(credentialsForIdentity.credentials().secretKey())
        .withSessionToken(credentialsForIdentity.credentials().sessionToken())
        .build()

5. Cognito认证有效性问题

  • 确认logins中的Key格式正确:cognito-idp.{region}.amazonaws.com/{userPoolId},同时检查ID Token是否有效、未过期。
  • 验证身份池已将对应Cognito用户池配置为身份提供者,且两者处于同一区域。

6. 客户端ID不符合规范

AWS IoT Core限制客户端ID最长128字符,且需符合MQTT 3.1.1格式要求。若客户端ID过长或包含非法字符,会被服务器拒绝连接。

内容的提问来源于stack exchange,提问作者MAGx2

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.23 12:13:11