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

使用临时STS凭证生成AWS IoT SigV4预签名WebSocket URL失败求助

问题

我正在使用AWS SDK for Go(v2)和v4签名器为AWS IoT Core生成SigV4预签名WebSocket URL。在概念验证环境中,使用长期凭证时一切正常,但使用从EKS集群获取的临时STS凭证时连接失败,提示权限拒绝。

以下是我用于签名的函数:

func generateSigV4URL(ctx context.Context, wsURL string, creds aws.Credentials, region string) (string, error) {
    u, err := url.Parse(wsURL)
    if err != nil {
        return "", err
    }

    req, err := http.NewRequest("GET", u.String(), nil)
    if err != nil {
        return "", err
    }

    emptyHash := sha256.Sum256([]byte{})
    payloadHash := hex.EncodeToString(emptyHash[:])

    signer := v4.NewSigner()

    signedURL, _, err := signer.PresignHTTP(
        ctx,
        creds,
        req,
        payloadHash,
        "iotdevicegateway",
        region,
        time.Now(),
    )
    if err != nil {
        return "", err
    }

    // Add session token for temporary credentials
    if creds.SessionToken != "" {
        u, _ := url.Parse(signedURL)
        q := u.Query()
        q.Set("X-Amz-Security-Token", creds.SessionToken)
        u.RawQuery = q.Encode()
        signedURL = u.String()
    }

    return signedURL, nil
}

使用临时凭证时,连接AWS IoT WebSocket端点失败,提示权限拒绝。请问如何在不破坏签名或双重编码令牌的前提下,正确将X-Amz-Security-Token包含到AWS IoT的SigV4预签名WebSocket URL中?

解决方案

问题核心是你在签名完成后才添加会话令牌,这会导致签名验证失败——SigV4签名计算需要包含所有请求参数,包括临时凭证的会话令牌。正确做法是在签名前就把X-Amz-Security-Token加入请求的查询参数,让签名器将其纳入签名计算范围。

修改步骤

  • 在解析原始WebSocket URL后,立即检查是否存在会话令牌,若存在则添加到查询参数中
  • 删除签名后添加令牌的逻辑,避免参数不一致导致的签名验证失败

修改后的代码

func generateSigV4URL(ctx context.Context, wsURL string, creds aws.Credentials, region string) (string, error) {
    u, err := url.Parse(wsURL)
    if err != nil {
        return "", err
    }

    // 签名前添加会话令牌到查询参数
    if creds.SessionToken != "" {
        q := u.Query()
        q.Set("X-Amz-Security-Token", creds.SessionToken)
        u.RawQuery = q.Encode()
    }

    req, err := http.NewRequest("GET", u.String(), nil)
    if err != nil {
        return "", err
    }

    emptyHash := sha256.Sum256([]byte{})
    payloadHash := hex.EncodeToString(emptyHash[:])

    signer := v4.NewSigner()

    signedURL, _, err := signer.PresignHTTP(
        ctx,
        creds,
        req,
        payloadHash,
        "iotdevicegateway",
        region,
        time.Now(),
    )
    if err != nil {
        return "", err
    }

    return signedURL, nil
}

关键注意事项

  • SigV4签名会对所有查询参数进行哈希计算,必须在签名前将X-Amz-Security-Token纳入参数列表,否则服务端验证时会因参数不匹配拒绝请求
  • url.Query().Set()会自动处理令牌的URL编码,无需手动操作,避免双重编码问题
  • 临时凭证的会话令牌是SigV4签名流程的一部分,必须参与签名计算,不能事后追加

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.12 06:13:15