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

非SDK调用Amazon Bedrock签名错误求助及代码示例需求

不使用AWS SDK调用Amazon Bedrock的Node.js/JS实现(修复签名不匹配问题)

问题根源分析

你的代码存在几个关键错误导致签名不匹配:

  • Host字段错误:将完整模型路径包含在host中,正确host应为bedrock-runtime.<region>.amazonaws.com,模型路径属于请求URI
  • Payload哈希计算错误:直接对JS对象计算哈希,需先序列化为标准JSON字符串再计算
  • 哈希与签名未转换为十六进制字符串:crypto-js的加密方法返回对象,需显式转为十六进制格式才能符合AWS签名要求
  • Canonical URI设置错误:未包含模型调用的完整路径

修复后的完整代码

import axios from 'axios';
import crypto from 'crypto-js';

async function callBedrock() {
    // AWS凭证
    const accessKey = "YOUR_ACCESS_KEY";
    const secretKey = "YOUR_SECRET_KEY";
    const method = 'POST';
    const service = 'bedrock';
    const region = 'eu-central-1';
    // 正确的Host:不包含模型路径
    const host = `bedrock-runtime.${region}.amazonaws.com`;
    // 完整的Canonical URI:包含模型调用路径
    const canonicalUri = '/model/anthropic.claude-v2:1/invoke';
    const baseUrl = `https://${host}`;
    const contentType = 'application/json';

    // 生成AWS要求的日期格式
    const amzDate = getAmzDate(new Date().toISOString());
    const dateStamp = amzDate.split("T")[0];

    // 请求Payload:注意格式符合Claude要求
    const payload = {
        "prompt": "\n\nHuman: Hello how are you\n\nAssistant:",
        "max_tokens_to_sample": 300,
        "temperature": 0.5,
        "top_k": 250,
        "top_p": 1,
        "anthropic_version": "bedrock-2023-05-31"
    };
    // 先将Payload序列化为标准JSON字符串,再计算SHA256哈希并转十六进制
    const payloadStr = JSON.stringify(payload);
    const payloadHash = crypto.SHA256(payloadStr).toString(crypto.enc.Hex);

    // 签名头部:按字母顺序排列(AWS要求)
    const signedHeaders = 'content-type;host;x-amz-content-sha256;x-amz-date';
    // 构建Canonical Headers:确保每个头部小写、值正确,末尾换行
    const canonicalHeaders = [
        `content-type:${contentType}`,
        `host:${host}`,
        `x-amz-content-sha256:${payloadHash}`,
        `x-amz-date:${amzDate}`
    ].join('\n') + '\n';

    // 构建Canonical Request
    const canonicalRequest = [
        method,
        canonicalUri,
        '', // 空的查询字符串
        canonicalHeaders,
        signedHeaders,
        payloadHash
    ].join('\n');
    // 计算Canonical Request的哈希
    const canonicalRequestHash = crypto.SHA256(canonicalRequest).toString(crypto.enc.Hex);

    // 构建待签名字符串
    const algorithm = 'AWS4-HMAC-SHA256';
    const credentialScope = `${dateStamp}/${region}/${service}/aws4_request`;
    const stringToSign = [
        algorithm,
        amzDate,
        credentialScope,
        canonicalRequestHash
    ].join('\n');

    // 生成签名密钥
    const signingKey = getSignatureKey(secretKey, dateStamp, region, service);
    // 计算签名并转十六进制
    const signature = crypto.HmacSHA256(stringToSign, signingKey).toString(crypto.enc.Hex);

    // 构建Authorization头部
    const authorizationHeader = `${algorithm} Credential=${accessKey}/${credentialScope}, SignedHeaders=${signedHeaders}, Signature=${signature}`;

    // 请求头部
    const headers = {
        'Authorization': authorizationHeader,
        'Content-Type': contentType,
        'X-Amz-Content-Sha256': payloadHash,
        'X-Amz-Date': amzDate
    };

    try {
        const response = await axios({
            method: method,
            baseURL: baseUrl,
            url: canonicalUri,
            data: payloadStr,
            headers: headers
        });
        console.log('Bedrock响应:', response.data);
    } catch (error) {
        console.error('请求失败:', error.response?.data || error.message);
    }
}

// 生成AWS要求的日期格式(YYYYMMDD'T'HHMMSS'Z')
function getAmzDate(dateStr) {
    let formatted = dateStr.replace(/[:-]/g, '');
    formatted = formatted.split('.')[0] + 'Z';
    return formatted;
}

// 生成AWS签名密钥
function getSignatureKey(key, dateStamp, regionName, serviceName) {
    const kDate = crypto.HmacSHA256(dateStamp, `AWS4${key}`);
    const kRegion = crypto.HmacSHA256(regionName, kDate);
    const kService = crypto.HmacSHA256(serviceName, kRegion);
    const kSigning = crypto.HmacSHA256('aws4_request', kService);
    return kSigning;
}

// 调用函数
callBedrock();

关键修改说明

  1. Host与URI分离:将模型路径从host移到canonicalUri,符合AWS服务的请求结构
  2. Payload哈希修正:先序列化为JSON字符串再计算哈希,确保和发送的请求体完全一致
  3. 哈希与签名的字符串转换:所有加密结果都通过.toString(crypto.enc.Hex)转为十六进制字符串,匹配AWS签名要求
  4. Canonical Headers构建:用数组拼接保证顺序正确,避免手动拼接的格式错误
  5. Prompt格式修正:Claude的prompt需要符合\n\nHuman: ...\n\nAssistant:的格式(原代码里的\n\Utterance是错误的)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 07:35:56