【问题标题】:Authorise Request to AWS WebSocket API Gateway using AWS_IAM使用 AWS_IAM 向 AWS WebSocket API 网关授权请求
【发布时间】:2020-05-14 19:13:23
【问题描述】:

我已经使用 WebSocket 协议设置了一个 API 网关。在“$connect”路由请求设置中,我选择了“AWS_IAM”作为授权方法。用户通过 Cognito 登录后,Web 应用程序需要与此 WebSocket API 建立连接。然后,我如何从 Web 应用程序上的 JavaScript 授权 WebSocket API 请求?使用 HTTP API 网关,我可以从传递到请求标头的访问密钥和会话令牌生成签名。但我无法在 WebSocket 请求中传递标头。

【问题讨论】:

    标签: amazon-web-services websocket aws-api-gateway amazon-iam api-gateway


    【解决方案1】:

    我从 AWS 支持部门得到了答复。我需要签署 wss URL。因此,不是在 HTTP 请求中设置请求标头,而是将签名信息传递给查询字符串参数中的 url。签名的 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 方法。

    【讨论】:

    • 嗨@Dean ..我试过了,你能提供任何代码示例吗?
    • 啊..现在可以工作了..下面发布了一些第一次迭代代码。
    • 这个答案似乎很好,但是,通过一些代码示例会变得更好。
    【解决方案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"
    }
    

    【讨论】:

    • 嗨 Rudi,在这种方法中,只要假定的 IAM 未过期,用户就可以登录吗?所以让我们说用户登录,然后更改密码。他是否能够使用先前生成的查询字符串继续使用端点,直到生成的令牌过期?
    • 这可能节省了我一些重要的时间。我尝试使用标准 Websocket 库,该库在没有身份验证的情况下工作正常,但在使用签名 URL 时失败并出现 403。 ``` 新的 WebSocket(url);
    【解决方案3】:

    我实现了这个对 AWS 请求 URL 进行签名的 Dart 代码。这对于连接到受 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})
    

    【讨论】:

      猜你喜欢
      • 2017-11-07
      • 2021-09-25
      • 2018-01-16
      • 2021-03-23
      • 2015-03-03
      • 2021-05-02
      • 2019-11-18
      • 2022-08-20
      • 1970-01-01
      相关资源
      最近更新 更多