连接到 websocket 以实时使用 amazon chime API

问题描述

我想使用 Amazon Chime API 扩展我用 JavaFX 编写的软件以使用其消息传递。我知道有 JS SDK 可以毫无问题地建立消息传递 websocket 会话。但是在 java SDK 中没有相关的类。所以我想使用 STOMP 库来消费 websocket 端点。

当时我正在努力制作正确的 request,即 signing AWS request(计算 X-AMZ-Signature)

根据 post,我正在尝试计算正确的 X-AMZ-Signature 请求参数。这是课程:

@Slf4j
@Service
public class Aws4Signer {
    
    private final static String REQUEST_CONTENT_TYPE = "application/json";
    private final static String AUTH_ALGORITHM = "AWS4-HMAC-SHA256";
    private final static String REQUEST_METHOD = "GET";

    @Data
    class AuthenticationData {
        @NonNull
        String timestamp;
        @NonNull
        String date;
        @NonNull
        String authorizationHeader;
    }
    
    private AppConfig appConfig = new AppConfig();

    /**
     * Gets the timestamp in YYYYMMDD'T'HHMMSS'Z' format,which is the required
     * format for AWS4 signing request headers and credential string
     *
     * @param dateTime
     *            an OffsetDateTime object representing the UTC time of current
     *            signing request
     * @return the formatted timestamp string
     *
     * @see <a href=
     *      "https://docs.aws.amazon.com/general/latest/gr/sigv4-signed-request-examples.html">
     *      Examples of the Complete Version 4 Signing Process (Python)</a>
     */
    public String getTimeStamp(OffsetDateTime dateTime) {
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMdd'T'HHmmss'Z'");
        String formatDateTime = dateTime.format(formatter);
        return formatDateTime;
    }

    /**
     * Gets the date string in yyyyMMdd format,which is required to build the
     * credential scope string
     *
     * @return the formatted date string
     */
    public String getDate(OffsetDateTime dateTime) {
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMdd");
        String formatDateTime = dateTime.format(formatter);
        return formatDateTime;
    }

    public byte[] generateAws4SigningKey(String timestamp) {
        String secretKey = appConfig.getAwsAuthConfig().getSecretKey();
        String regionName = appConfig.getAwsAuthConfig().getServiceRegion();
        String serviceName = appConfig.getAwsAuthConfig().getServiceName();

        byte[] signatureKey = null;
        try {
            signatureKey = Aws4SignatureKeyGenerator.generateSignatureKey(secretKey,timestamp,regionName,serviceName);
        } catch (Exception e) {
            log.error("An error has ocurred when generate signature key: " + e,e);
        }

        return signatureKey;
    }

    /**
     * Builds an {@link AuthenticationData} object containing the timestamp,date,* payload hash and the AWS4 signature
     * <p>
     *
     * The signing logic was translated from the Python implementation,see this
     * link for more details: <a href=
     * "https://docs.aws.amazon.com/general/latest/gr/sigv4-signed-request-examples.html">Examples
     * of the Complete Version 4 Signing Process (Python)</a>
     *
     * @param target
     * @param requestBody
     *
     * @return
     * @throws NoSuchAlgorithmException
     * @throws UnsupportedEncodingException
     * @throws InvalidKeyException
     * @throws SignatureException
     * @throws IllegalStateException
     *
     */
    public AuthenticationData buildAuthorizationData() throws NoSuchAlgorithmException,UnsupportedEncodingException,InvalidKeyException,SignatureException,IllegalStateException {
        log.info("predict - start");

        // Starting building the lengthy signing data
        AwsAuthConfig awsAuthConfig = appConfig.getAwsAuthConfig();
        String payloadHash = Hmac.getSha256Hash(requestBody);

        OffsetDateTime Now = OffsetDateTime.Now(ZoneOffset.UTC);
        String timestamp = getTimeStamp(Now);
        String date = getDate(Now);

        // Step 1 is to define the verb (GET,POST,etc.) -- already done by defining
        // constant REQUEST_METHOD

        // Step 2: Create canonical URI--the part of the URI from domain to query
        // string (use '/' if no path)
        String canonical_uri = "/connect";

        // Step 3: Create the canonical query string. In this example,request
        // parameters are passed in the body of the request and the query string
        // is blank.
        String canonical_querystring = buildCanonicalQueryString();

        // Step 4: Create the canonical headers. Header names must be trimmed
        // and lowercase,and sorted in code point order from low to high.
        // Note that there is a trailing \n.
        String canonical_headers = "content-type:" + REQUEST_CONTENT_TYPE + "\n"
                                 + "host:" + awsAuthConfig.getServiceHost() + "\n"
                                 + "x-amz-date:" + timestamp + "\n";
        
        String signed_headers = "content-type;host;x-amz-date";

        log.debug("canonical_headers : {}",canonical_headers);

        String canonical_request = REQUEST_METHOD + "\n" + canonical_uri + "\n" + canonical_querystring + "\n"
                + canonical_headers + "\n" + signed_headers;

        log.debug("canonical_request : {}",canonical_request);

        String credential_scope = date + "/" + awsAuthConfig.getServiceRegion() + "/" + awsAuthConfig.getServiceName()
                + "/" + "aws4_request";
        String canonical_request_hash = Hmac.getSha256Hash(canonical_request);

        log.debug("canonical_request_hash : {}",canonical_request_hash);

        String string_to_sign = AUTH_ALGORITHM + "\n" + timestamp + "\n" + credential_scope + "\n"
                + canonical_request_hash;

        log.debug("string_to_sign : {}",string_to_sign);
        byte[] sigKey = generateAws4SigningKey(date);

        String signature = Hmac.calculateHMAC(string_to_sign,sigKey,Hmac.HMAC_SHA256);
        String authorization_header = AUTH_ALGORITHM + " " + "Credential=" + awsAuthConfig.getAccessKey() + "/"
                + credential_scope + "," + "SignedHeaders=" + signed_headers + "," + "Signature=" + signature;

        log.debug("authorization_header : {}",authorization_header);

        return new AuthenticationData(timestamp,authorization_header);
    }

    private String buildCanonicalQueryString() {
        String canonicalRequest = REQUEST_METHOD + "\n" +
                                 "/connect" + "\n" +
                "X-Amz-Algorithm=AWS4-HMAC-SHA256\n" +
                "&X-Amz-Credential=MYACCESKEY%2F"+ getDate(OffsetDateTime.Now()) + "%2Fus-east-1%2Fchime%2Faws4_request\n" +
                "&X-Amz-Date=" + getTimeStamp(OffsetDateTime.Now()) +"\n" +
                "&X-Amz-Expires=10\n" +
                "&X-Amz-SignedHeaders=host\n" +
                "&sessionId=" + UUID.randomUUID() +"\n" +
                "&userArn=" + "MYUSERARN";

        return canonicalRequest;
    }

}

提供的信息

  • 主机:node001.ue1.ws-messaging.chime.aws
  • 服务名称:chime
  • 区域:us-east-1

生成签名,我正在尝试通过邮递员使用它,但邮递员无法连接到端点 node001.ue1.ws-messaging.chime.aws/connect,只是说“连接 ETIMEDOUT 54.162.103.101: 80'。

我是亚马逊的新手,所以对我来说有点困难。你能说我错在哪里吗?

感谢任何帮助!

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...