Подпись не соответствует ошибке при вызове API Bedrock с использованием кода Java с SDKJAVA

Программисты JAVA общаются здесь
Ответить Пред. темаСлед. тема
Anonymous
 Подпись не соответствует ошибке при вызове API Bedrock с использованием кода Java с SDK

Сообщение Anonymous »

Я пытаюсь вызвать API AWS Bedrock, используя Java, не используя AWS SDK. Тем не менее, я продолжаю получать запретную ошибку 403 с сообщением «несоответствие подписи». Тот же запрос отлично работает в Python. < /P>
ниже мой код Java: < /p>

Код: Выделить всё

@Service
public class AnthropicServiceImpl {

private static final String AWS_ACCESS_KEY_ID = "accesskeyid";
private static final String AWS_SECRET_ACCESS_KEY = "secretkey";

private static final String METHOD = "POST";
private static final String SERVICE = "bedrock";
private static final String REGION = "us-east-1";
private static final String ALGORITHM = "AWS4-HMAC-SHA256";
private static final String HOST = "bedrock-runtime.us-east-1.amazonaws.com";
private static final String ENDPOINT_PATH = "/model/anthropic.claude-3-haiku-20240307-v1:0/invoke";

public static void main(String[] args) throws Exception {
// Use TreeMap to ensure consistent ordering of headers
TreeMap headers = new TreeMap();

String payload = "{"
+ "\"anthropic_version\": \"bedrock-2023-05-31\","
+ "\"max_tokens\": 512,"
+ "\"messages\": ["
+ "    {"
+ "        \"role\": \"user\","
+ "        \"content\": ["
+ "            {"
+ "                \"type\": \"text\","
+ "                \"text\": \"What is java\""
+ "            }"
+ "        ]"
+ "    }"
+ "]"
+ "}";

// Create a datetime object for signing
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd'T'HHmmss'Z'", Locale.US);
dateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
String amzDate = dateFormat.format(new Date());
String dateStamp = amzDate.substring(0, 8);

// Calculate payload hash
String payloadHash = sha256Hex(payload);
String contentLength = String.valueOf(payload.getBytes(StandardCharsets.UTF_8).length);

// Add headers to TreeMap to ensure consistent ordering
headers.put("accept", "application/json");
headers.put("content-length", contentLength);
headers.put("content-type", "application/json");
headers.put("host", HOST);
headers.put("x-amz-content-sha256", payloadHash);
headers.put("x-amz-date", amzDate);
headers.put("x-amzn-bedrock-save", "true");

// Build canonical headers and signed headers string
StringBuilder canonicalHeadersBuilder = new StringBuilder();
StringBuilder signedHeadersBuilder = new StringBuilder();

boolean first = true;
for (String key : headers.keySet()) {
canonicalHeadersBuilder.append(key.toLowerCase())
.append(":")
.append(headers.get(key).trim())
.append("\n");

if (!first) {
signedHeadersBuilder.append(";");
}
signedHeadersBuilder.append(key.toLowerCase());
first = false;
}

String canonicalHeaders = canonicalHeadersBuilder.toString();
String signedHeaders = signedHeadersBuilder.toString();

// Create canonical request
String canonicalRequest = METHOD + "\n"
+ ENDPOINT_PATH + "\n"
+ "\n"  // Empty query string
+ canonicalHeaders + "\n"
+ signedHeaders + "\n"
+ payloadHash;

// Create string to sign
String credentialScope = String.format("%s/%s/%s/aws4_request", dateStamp, REGION, SERVICE);
String stringToSign = ALGORITHM + "\n"
+ amzDate + "\n"
+ credentialScope + "\n"
+ sha256Hex(canonicalRequest);

System.out.println("Canonical Request:\n" + canonicalRequest);
System.out.println("\nString to Sign:\n"  + stringToSign);

// Calculate signature
byte[] signingKey = getSignatureKey(AWS_SECRET_ACCESS_KEY, dateStamp, REGION, SERVICE);
String signature = hmacSha256Hex(signingKey, stringToSign);

// Create authorization header
String authorizationHeader = String.format("%s Credential=%s/%s, SignedHeaders=%s, Signature=%s",
ALGORITHM, AWS_ACCESS_KEY_ID, credentialScope, signedHeaders, signature);

// Make the request
URL url = new URL("https://" + HOST + ENDPOINT_PATH);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setDoOutput(true);
conn.setRequestMethod(METHOD);

// Set all headers from our TreeMap
for (String key : headers.keySet()) {
conn.setRequestProperty(key, headers.get(key));
}
conn.setRequestProperty("Authorization", authorizationHeader);

// Print request details for debugging
System.out.println("\nAuthorization Header:\n" + authorizationHeader);
System.out.println("\nPayload Hash: " + payloadHash);

// Send payload
try (OutputStream os = conn.getOutputStream()) {
byte[] input = payload.getBytes(StandardCharsets.UTF_8);
os.write(input, 0, input.length);
}

// Get response
int responseCode = conn.getResponseCode();
if (responseCode == HttpURLConnection.HTTP_OK) {
String response = new String(conn.getInputStream().readAllBytes(), StandardCharsets.UTF_8);
System.out.println("Response: " + response);
} else {
System.out.println("Error: " + responseCode + " " + conn.getResponseMessage());
String errorResponse = new String(conn.getErrorStream().readAllBytes(), StandardCharsets.UTF_8);
System.out.println("Error details: " + errorResponse);
}
}

private static byte[] getSignatureKey(String key, String dateStamp, String regionName, String serviceName) {
try {
byte[] kSecret = ("AWS4"  + key).getBytes(StandardCharsets.UTF_8);
byte[] kDate = hmacSha256(kSecret, dateStamp);
byte[] kRegion = hmacSha256(kDate, regionName);
byte[] kService = hmacSha256(kRegion, serviceName);
return hmacSha256(kService, "aws4_request");
} catch (Exception e) {
throw new RuntimeException("Error calculating signing key", e);
}
}

private static byte[] hmacSha256(byte[] key, String data) throws NoSuchAlgorithmException, InvalidKeyException {
Mac mac = Mac.getInstance("HmacSHA256");
mac.init(new SecretKeySpec(key, "HmacSHA256"));
return mac.doFinal(data.getBytes(StandardCharsets.UTF_8));
}

private static String hmacSha256Hex(byte[] key, String data) {
try {
return bytesToHex(hmacSha256(key, data));
} catch (Exception e) {
throw new RuntimeException("Error calculating HMAC", e);
}
}

private static String sha256Hex(String data) throws NoSuchAlgorithmException {
MessageDigest digest = MessageDigest.getInstance("SHA-256");
byte[] hash = digest.digest(data.getBytes(StandardCharsets.UTF_8));
return bytesToHex(hash);
}

private static String bytesToHex(byte[] bytes) {
StringBuilder result = new StringBuilder();
for (byte b : bytes) {
result.append(String.format("%02x", b));
}
return result.toString();
}
}
< /code>
Код Python работает: < /p>
import boto3
import json
from botocore.awsrequest import AWSRequest
from botocore.auth import SigV4Auth
from botocore.credentials import Credentials

# AWS credentials
access_key = "access key"
secret_key = "secret key"

# Service and region
service = "bedrock"
region = "us-east-1"

# Request details
url = "https://bedrock-runtime.us-east-1.amazonaws.com/model/anthropic.claude-3-haiku-20240307-v1:0/invoke"
payload = {
"messages": [{"role": "user", "content": "What is python?"}],
"temperature": 0.5,
"top_p": 0.9,
"max_tokens": 512,
"anthropic_version": "bedrock-2023-05-31",  # Set version to a valid one
}
headers = {
"Accept": "application/json",
"X-Amzn-Bedrock-Save": "true",
"Content-Type": "application/json",
}

# Create AWS request
request = AWSRequest(method="POST", url=url, data=json.dumps(payload), headers=headers)
credentials = Credentials(access_key, secret_key)
SigV4Auth(credentials, service, region).add_auth(request)

# Create an HTTP client manually using botocore for sending the request
import botocore.session

# Create a botocore session
session = botocore.session.get_session()
client = session.create_client(service, region_name=region, aws_access_key_id=access_key, aws_secret_access_key=secret_key)

# Send the prepared request using the client
http_session = client._endpoint.http_session
response = http_session.send(request.prepare())

# Debugging
print("Payload Sent:")
print(json.dumps(payload, indent=4))
print("\nResponse:")
print(response.text)
< /code>
полезная нагрузка отправлена: < /p>
{
"messages": [
{
"role": "user",
"content": "What is python?"
}
],
"temperature": 0.5,
"top_p": 0.9,
"max_tokens": 512,
"anthropic_version": "bedrock-2023-05-31"
}
< /code>
Ответ:  < /p>
{"id":"msg_bdrk_01YDAcio1xXTfXMkL6xhheNz","type":"message","role":"assistant","model":"claude-3-haiku-20240307","content":[{"type":"text","text":"Python is a high-level, general-purpose programming language."}],"stop_reason":"end_turn","stop_sequence":null,"usage":{"input_tokens":11,"output_tokens":318}}
Как тот же запрос отлично работает в Python, в чем проблема с кодом Java?


Подробнее здесь: https://stackoverflow.com/questions/793 ... va-code-wi
Реклама
Ответить Пред. темаСлед. тема

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

  • Похожие темы
    Ответы
    Просмотры
    Последнее сообщение

Вернуться в «JAVA»