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

使用IAM临时凭证调用AWS API:C#代码认证失败但Postman成功

AWS SigV4A签名认证失败排查(C#代码)

我通过AssumeRole获取临时凭证,再用该凭证通过SigV4A签名调用AWS服务API,代码返回Authentication Error,但将相同临时凭证放到Postman中请求完全正常。

相关代码

获取临时凭证代码

private static async Task<Aws.Crt.Auth.Credentials> GetTemporaryCredentialsAsync()
{
    using (var stsClient = new AmazonSecurityTokenServiceClient(aws_access_key_id, aws_secret_access_key))
    {
        var response = await stsClient.AssumeRoleAsync(new AssumeRoleRequest
        {
            RoleArn = "arn:aws:iam::77790******:role/AmazonLendingAPIRole",
            RoleSessionName = "Assume123",
            DurationSeconds = 3600
        });

        Credentials credentials = response.Credentials;

        var sessionCredentials =
            new Aws.Crt.Auth.Credentials(credentials.AccessKeyId,
                                      credentials.SecretAccessKey,
                                      credentials.SessionToken);
        return sessionCredentials;
    }
}

SigV4A签名方法

public IEnumerable<HttpHeader> SignRequest(string method, string region, string endpoint, string service, Credentials credentials)
{
    var endpointUri = new Uri(endpoint);
    var request = new HttpRequest
    {
        Method = method,
        Uri = endpointUri.PathAndQuery,
        Headers = new[] { new HttpHeader("host", endpointUri.Host) }
    };

    var config = new AwsSigningConfig
    {
        Service = service,
        Region = region,
        Algorithm = AwsSigningAlgorithm.SIGV4A,
        SignatureType = AwsSignatureType.HTTP_REQUEST_VIA_HEADERS,
        SignedBodyHeader = AwsSignedBodyHeaderType.X_AMZ_CONTENT_SHA256,
        Credentials = credentials,
    };

    var result = AwsSigner.SignHttpRequest(request, config);
    AwsSigner.CrtSigningResult signingResult = result.Get();
    HttpRequest signedRequest = signingResult.SignedRequest;

    return signedRequest.Headers;
}

发起请求代码

var signingService = new SigV4ASign();
var assumeRoleUserCredentials = await GetTemporaryCredentialsAsync(); ;

var endpoint = endpoint_get_offer;
var awsCredentials = new Aws.Crt.Auth.Credentials(assumeRoleUserCredentials.AccessKeyId, assumeRoleUserCredentials.SecretAccessKey, assumeRoleUserCredentials.SessionToken);

var method = HttpMethod.Get;

var headers = signingService.SignRequest(method.Method, "eu-west-1", endpoint, "execute-api", awsCredentials);

using var client = new HttpClient();
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Clear();
foreach (var header in headers)
{
    client.DefaultRequestHeaders.TryAddWithoutValidation(header.Name, header.Value);
}
client.DefaultRequestHeaders.TryAddWithoutValidation("x-api-key", "WEuqF5RDOi5R1pza2601***************");

var response = await client.GetAsync(endpoint);

IAM用户配置截图

IAM用户配置截图

排查方向

  • 签名Region一致性:确认Postman使用的Region与代码中eu-west-1完全匹配,SigV4A签名对Region敏感,即使是多Region服务也需保证签名Region与请求目标Region一致。
  • Host头校验:代码签名时已添加host头,但HttpClient可能自动覆盖该头,需检查最终请求的Host是否与签名时的endpointUri.Host完全一致(含端口)。
  • 请求参数一致性:对比Postman与代码的完整请求路径(含Query String),确保签名时的endpointUri.PathAndQuery与实际请求的路径参数、编码、顺序完全相同。
  • 签名Headers完整性:检查签名生成的所有Headers(如Authorization、x-amz-date、x-amz-security-token)是否全部被HttpClient正确携带,未被默认设置覆盖。
  • Body哈希配置:代码中设置SignedBodyHeader = AwsSignedBodyHeaderType.X_AMZ_CONTENT_SHA256,需确认Postman使用相同的Body哈希方式;GET请求Body为空时,x-amz-content-sha256应对应空哈希或UNSIGNED-PAYLOAD。
  • 临时凭证传递:验证AssumeRole获取的临时凭证(AccessKeyId、SecretAccessKey、SessionToken)是否完整、无错误地传递到签名方法中。

内容的提问来源于stack exchange,提问作者Fazla Elahi Md Jubayer

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 02:20:28