当前位置: 首页 > 知识库问答 >
问题:

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

富钧
2023-03-14

我想扩展我的软件,用JavaFX编写,使用Amazon Chime API来使用它的消息传递。我知道有JS SDK允许建立消息网络套接字会话没有问题。但是在java SDK中没有相关的类。所以我想使用STOMP库来消费webSocketendpoint。

当时我正努力提出正确的请求,即签署AWS请求(计算X-AMZ-Signature)

根据帖子我试图计算正确的X-AMZ签名请求参数。课程是这样的:

@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, date, 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
  • 地区:美国东部1

它生成签名,我正试图通过postman使用它,但postman无法连接到endpointnode001.ue1.ws-messaging.chime.aws/connect,只说“connect-ETIMEDOUT 54.162.103.101:80”。

我刚到亚马逊,所以对我来说有点难。你能说我哪里错了吗?

感谢您的帮助!

共有1个答案

诸嘉澍
2023-03-14

为连接到chime websocket的URL签名编写了完整的工作代码。希望这能帮助别人!

 类似资料:
  • 我正在使用套接字。io,应用程序由AWS提供。我收到一个浏览器控制台错误: websocket.js:54 WebSocket 连接到 'wss://www.tidee.com/socket.io/?EIO=4 客户代码: 服务器代码: 在 AWS 中,安全组接受端口 443,负载均衡器侦听端口 443。 应用程序在本地运行时工作(状态 101),并使用 协议。

  • 我得到一个连接不打开发送()错误后立即连接到一个万花筒节点的网络套接字。我试图从web3js版本1.0.0-beta.34使用WebSocketProvider。 我的连接代码看起来像这样,其中,和是带有Kaleido节点信息的局部变量。 我已经尝试了Github问题中列出的建议步骤——在连接丢失时尝试重新连接,但错误仍然存在。我认为这可能是一个Kaleido问题,因为我可以使用Websocket

  • 问题内容: 尝试使用socket.io- client连接到用Go编写的websocket服务器。我已经使用节点WebSocket库(npm)成功连接。因此,有效的Websocket代码如下所示: 非常简单并且有效-另一端的套接字以设定的频率发送消息。但是我最初尝试使用(npm),但是无法继续使用。它肯定将websocket列为其首选传输,但是该死,如果我能连接它的话: 连接永远不会发生,因此不会

  • 我正在创建一个聊天应用程序,其WebSocket服务器是用java编写的。 对于WebSocket客户端,我正在使用SocketRocket库。 当我尝试从本地主机或127.0.0.1连接时,一切正常 但当我尝试使用公共IP连接它时,它在

  • 我正在制作一个Flask网络应用程序,我正在使用Flask Socketio。出于各种原因,我还需要使用websocket客户端包。一切正常,但当我尝试在不同网络上的不同计算机上运行应用程序时,出现以下错误: 我已经尽可能地将我的代码归结为以下内容,这些代码在我的计算机上仍然有效,但在另一台计算机上给出了相同的错误: 只是一个基本的“Hello World”html页面。 什么样的东西会让我在一台