

# 使用 WebSocket 库生成预签名请求
<a name="network-analyzer-generate-request"></a>

下面显示如何生成预签名请求，这样，您就可以使用 WebSocket 库向服务发送请求。

## 将 WebSocket 请求的策略添加到您的 IAM 角色
<a name="network-analyzer-iam"></a>

要使用 WebSocket 协议调用网络分析器，您需要将以下策略附加到发出请求的 AWS Identity and Access Management(IAM) 角色。

```
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": "iotwireless:StartNetworkAnalyzerStream",
            "Resource": "*"
        }
    ]
}
```

## 创建预签名 URL
<a name="network-analyzer-presigned-url"></a>

为 WebSocket 请求构造一个 URL，该请求中包含在应用程序和网络分析器 之间建立通信所需的信息。要验证请求的标识，WebSocket 流式处理使用 Amazon 签名版本 4 流程处理签名请求。有关签名版本4的更多信息，请参阅 *Amazon Web Services 一般参考*中的[签名 AWSAPI 请求](https://docs.aws.amazon.com/general/latest/gr/signing_aws_api_requests.html)。

要调用网络分析器，请使用 `StartNetworkAnalyzerStream`请求 URL。使用之前提到的 IAM 角色凭据对请求进行签名。URL的格式如下，出于可读性目的，添加了换行符。

```
GET wss://api.iotwireless.<region>.amazonaws.com/start-network-analyzer-stream?X-Amz-Algorithm=AWS4-HMAC-SHA256
   &X-Amz-Credential=Signature Version 4 credential scope
   &X-Amz-Date=date
   &X-Amz-Expires=time in seconds until expiration
   &X-Amz-Security-Token=security-token
   &X-Amz-Signature=Signature Version 4 signature 
   &X-Amz-SignedHeaders=host
```

对于签名版本 4 参数，请使用以下值：
+ **X-Amz-Algorithm** – 您在签名过程中使用的算法。唯一有效值为 `AWS4-HMAC-SHA256`。
+ **X-Amz-Credential** – 以斜杠（“/”）分隔的字符串，它通过将您的访问密钥 ID 和凭证范围组件串联起来而形成。凭证范围包括采用 YYYYMMDD 格式的日期、AWS 区域、服务名称和终止字符串 (aws4\$1request)。
+ **X-Amz-Date** – 创建签名的日期和时间。根据 *Amazon Web Services 一般参考*中[签名版本 4 中处理日期](https://docs.aws.amazon.com/general/latest/gr/sigv4-date-handling.html)的说明生成日期和时间。
+ **X-Amz-Expires** – 凭证到期之前的时间长度（以秒为单位）。最大值为 300 秒（5 分钟）。
+ **X-Amz-Security-Token** – 临时凭证的签名版本 4 令牌。如果您指定此参数，则将其包含在规范请求中。更多信息，请参阅 *AWSIdentity and Access Management *中的[请求临时安全凭据。](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_request.html)
+ **X-Amz-Signature** – 您为请求生成的签名版本 4 签名。
+ **X-Amz-SignedHeaders** – 在为请求创建签名时签名的标头。唯一有效值为 `host`。

## 构建请求 URL 并创建签名版本 4 签名
<a name="connect-iot-network-analyzer-construct-url-sign"></a>

要构造请求的 URL 并创建签名版本 4 签名，请使用以下步骤。这些示例是伪代码。

### 任务 1：创建规范请求
<a name="canonical-request"></a>

创建一个字符串，其中包含来自标准格式的请求的信息。这可确保 AWS在收到请求时，计算出的签名与您在 [任务 3：计算签名](#calculate-signature)中计算出的签名相同。有关更多信息，请参阅 *Amazon Web Services 一般参考*中的 [创建签名版本 4 的规范请求](https://docs.aws.amazon.com/general/latest/gr/sigv4-create-canonical-request.html)。

1. 为您应用程序中的请求定义变量。

   ```
   # HTTP verb
   method = "GET"
   # Service name
   service = "iotwireless"
   # AWS 区域
   region = "AWS 区域"
   # Service streaming endpoint
   endpoint = "wss://api.iotwireless.region.amazonaws.com"
   # Host
   host = "api.iotwireless.<region>.amazonaws.com"
   # Date and time of request
   amz-date = YYYYMMDD'T'HHMMSS'Z'
   # Date without time for credential scope
   datestamp = YYYYMMDD
   ```

1. 创建规范 URI（统一资源标识符）。规范 URI 是域与查询字符串之间的 URI 部分。

   ```
   canonical_uri = "/start-network-analyzer-stream"
   ```

1. 创建规范标头和签名标头。请注意规范标头尾部的 `\n`。
   + 追加小写标头名称，后跟冒号。
   + 追加该标头的值的逗号分隔列表。请勿对有多个值的标头进行值排序。
   + 追加一个新行(`\n`)。

   ```
   canonical_headers = "host:" + host + "\n"
   signed_headers = "host"
   ```

1. 将算法与哈希算法匹配。您必须使用 SHA-256。

   ```
   algorithm = "AWS4-HMAC-SHA256"
   ```

1. 创建凭证范围，该范围将派生密钥范围限定为发出请求的日期以及将请求发送到的区域和服务。

   ```
   credential_scope = datestamp + "/" + region + "/" + service + "/" + "aws4_request"
   ```

1. 创建规范查询字符串。查询字符串值必须是 URL 编码，并且按名称排序。
   + 按字符代码点以升序顺序对参数名称进行排序。具有重复名称的参数应按值进行排序。例如，以大写字母 F 开头的参数名称排在以小写字母 b 开头的参数名称之前。
   + 请勿对 [RFC 3986](https://datatracker.ietf.org/doc/html/rfc3986) 定义的任何非预留字符进行 URI 编码，这些字符包括：A-Z、a-z、0-9、连字符 (-)、下划线 (\$1)、句点 (.) 和波形符 (\$1)。
   + 使用 %XY 对所有其他字符进行百分比编码，其中“X”和“Y”为十六进制字符（0-9 和大写字母 A-F）。例如，空格字符必须编码为 %20（不像某些编码方案那样使用“\$1”)，扩展 UTF-8 字符必须采用格式 %XY%ZA%BC。
   + 对参数值中的任何等于 (=) 字符进行双重编码。

   ```
   canonical_querystring  = "X-Amz-Algorithm=" + algorithm
   canonical_querystring += "&X-Amz-Credential="+ URI-encode(access key + "/" + credential_scope)
   canonical_querystring += "&X-Amz-Date=" + amz_date 
   canonical_querystring += "&X-Amz-Expires=300"
   canonical_querystring += "&X-Amz-Security-Token=" + token
   canonical_querystring += "&X-Amz-SignedHeaders=" + signed_headers
   canonical_querystring += "&language-code=en-US&media-encoding=pcm&sample-rate=16000"
   ```

1. 创建负载的哈希。对于 GET 请求，负载为空字符串。

   ```
   payload_hash = HashSHA256(("").Encode("utf-8")).HexDigest()
   ```

1. 组合所有元素以创建规范请求。

   ```
   canonical_request = method + '\n' 
      + canonical_uri + '\n' 
      + canonical_querystring + '\n' 
      + canonical_headers + '\n' 
      + signed_headers + '\n' 
      + payload_hash
   ```

### 任务 2：创建待签字符串
<a name="create-urlsign"></a>

待签字符串包含您的请求的元信息。在计算请求签名时，您可以使用该字符串登录下一步。有关更多信息，请参阅《Amazon Web Services 一般参考》**中的[创建签名版本 4 签名字符串](https://docs.aws.amazon.com/general/latest/gr/sigv4-create-string-to-sign.html)。

```
string_to_sign=algorithm + "\n"
   + amz_date + "\n"
   + credential_scope + "\n"
   + HashSHA256(canonical_request.Encode("utf-8")).HexDigest()
```

### 任务 3：计算签名
<a name="calculate-signature"></a>

您可以从您的 AWS秘密访问密钥派生签名密钥。为了实现更高程度的保护，派生密钥特定于日期、服务和 AWS区域。您可以使用派生密钥签名请求。有关更多信息，请参阅《Amazon Web Services 一般参考》[https://docs.aws.amazon.com/general/latest/gr/sigv4-calculate-signature.html](https://docs.aws.amazon.com/general/latest/gr/sigv4-calculate-signature.html)中的*为 AWS 签名版本 4 计算签名*。

该代码假定您实施了函数 `GetSignatureKey`来派生签名密钥。有关更多信息，请参阅 [Amazon Web Services 一般参考](https://docs.aws.amazon.com/general/latest/gr/signature-v4-examples.html)中的*如何为签名版本 4 派生签名密钥的示例*。

函数 `HMAC(key, data)`表示以二进制格式返回结果的 HMAC-SHA256 函数。

```
#Create the signing key
signing_key = GetSignatureKey(secret_key, datestamp, region, service)
                
# Sign the string_to_sign using the signing key
signature = HMAC.new(signing_key, (string_to_sign).Encode("utf-8"), Sha256()).HexDigest
```

### 任务 4：将签名信息添加到请求中并创建请求 URL
<a name="sign-request"></a>

在计算签名之后，将它添加到查询字符串。有关更多信息，请参阅 *Amazon Web Services 一般参考*中的[向请求添加签名](https://docs.aws.amazon.com/general/latest/gr/sigv4-add-signature-to-request.html)。

```
#Add the authentication information to the query string
canonical_querystring += "&X-Amz-Signature=" + signature
                
# Sign the string_to_sign using the signing key
request_url = endpoint + canonical_uri + "?" + canonical_querystring
```

## 后续步骤
<a name="network-analyzer-request-next"></a>

现在，您可以在 WebSocket 库中使用请求 URL 向服务发出请求并观察消息。有关更多信息，请参阅[WebSocket 消息和状态码](network-analyer-messages-status.md)。