我已经使用WebSocket协议设置了API网关。在“ $ connect”路由请求设置上,我选择了“ AWS_IAM”作为授权方法。用户通过Cognito登录后,Web应用程序需要与此WebSocket API建立连接。然后如何通过Web应用程序上的JavaScript授权WebSocket API请求?使用HTTP API网关,我可以根据访问密钥和会话令牌生成签名,这些签名已传递到请求标头中。但是我无法在WebSocket请求中传递标头。
答案 0 :(得分:2)
我从AWS支持部门得到了答案。我将需要签署wss URL。因此,签名信息将传递给查询字符串参数中的url,而不是在HTTP请求中设置请求标头。签名的wss URL看起来像:wss://API_ID.execute-api.region.amazonaws.com/dev?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=ACCESSKEY/20200131/region/execute-api/aws4_request&X-Amz-Date=20200131T100233Z&X-Amz-Security-Token=SECURITY_TOKEN&X-Amz-SignedHeaders=host&X-Amz-Signature=SIGNATURE
。
要生成签名的URL,可以使用@ aws-amplify / core库中的Signer.signUrl方法。
答案 1 :(得分:2)
这是一些对我有用的示例/伪代码:
使用AWS Amplify身份验证用户:
import { w3cwebsocket as W3CWebSocket } from "websocket"
import { Auth, Signer } from "aws-amplify"
let wsClient: any = null
export const client = async () => {
if (wsClient) return wsClient
if ((await Auth.currentUserInfo()) === null) return wsClient
const credentials = await Auth.currentCredentials()
const accessInfo = {
access_key: credentials.accessKeyId,
secret_key: credentials.secretAccessKey,
session_token: credentials.sessionToken,
}
const wssUrl = "wss://YOUR-API-ID.execute-api.REGION.amazonaws.com/dev"
const signedUrl = Signer.signUrl(wssUrl, accessInfo)
wsClient = new W3CWebSocket(signedUrl)
wsClient.onerror = function () {
console.log("[client]: Connection Error")
}
wsClient.onopen = function () {
console.log("[client]: WebSocket Client Connected")
}
wsClient.onclose = function () {
console.log("[client]: Client Closed")
}
wsClient.onmessage = function (e: any) {
if (typeof e.data === "string") {
console.log("Received: '" + e.data + "'")
}
}
return wsClient
}
然后还使用AWS Cognito需要此权限:
{
"Action": ["execute-api:Invoke"],
"Resource": "arn:aws:execute-api:REGION:ACCOUNT-ID-OR-WILDCARD:*/*/$connect",
"Effect": "Allow"
}
答案 2 :(得分:0)
我实现了此 Dart 代码,用于签署 AWS 请求 URL。这对于连接到受 IAM 保护的 WebSocket API 网关特别有用。
https://github.com/MohammedNoureldin/aws-url-signer
我知道不鼓励在答案中放置链接,但是在这里复制整个 100 行代码是没有意义的。
我的实现的用法如下所示:
String getSignedWebSocketUrl(
{String apiId,
String region,
String stage,
String accessKey,
String secretKey,
String sessionToken})