【问题标题】:Signing AWS Api Gateway request in Unity3D C#在 Unity3D C# 中签署 AWS Api Gateway 请求
【发布时间】:2017-07-10 08:25:32
【问题描述】:

我正在使用 Unity3D v5.5.1 和 AWS-SDK-Unity v3.3.37.0。 由于 Api 网关不会为 C#/Unity3D 生成 SDK,我正在尝试自行签署 (SigV4) 请求,但遇到了困难。

我已经尝试过 manually signing 和使用 AWS4Signer.cs 类。

Api Gateway 方法具有 Invoke with caller credentials,并且只返回一个 Hello World 作为响应。

在统一内,我有一个 facebook 登录按钮,它返回 FB 凭据和令牌。使用 Cognito Federated Identity 的 GetCredentialsAsync 方法,我得到一个带有 Key、Secret 和 TokenImmutableCredentials 对象。

要访问 api 网关 url,我在这里使用 AWS4Signer 类来构建签名请求。在下面的示例中,我尝试将安全令牌添加到 url 参数和不添加安全令牌,也对其进行签名而不使用令牌进行签名。所有选项都不起作用(如this post 所述)

这会导致以下任一响应: 1.我们计算的请求签名与您提供的签名不符

  1. 请求中包含的安全令牌无效。

如何正确签署来自 Unity3D 的请求?

提前致谢

TestGet 方法:

IEnumerator TestGet (ImmutableCredentials response)
        {
            ApiGatewayConfig clientConfig = new ApiGatewayConfig(); // a class I created wrapping the ClientConfig.cs
            var metrics = new RequestMetrics();

            var awsAccessKeyId = response.AccessKey;
            var awsSecretAccessKey = response.SecretKey;
            var awsToken = response.Token;

            AmazonWebServiceRequest req = new MyRequest(); // a clas I created wrapping the AmazonWebServiceRequest.cs class

            var url = "https://<url_to_api>.execute-api.us-east-1.amazonaws.com/dev/securehello";

            IRequest request = new DefaultRequest(req,"execute-api");
            request.UseQueryString = true;

            request.HttpMethod = "GET";
            request.Endpoint = new System.Uri (url);
            request.ResourcePath = url;
            request.ContentStream = new MemoryStream();
            request.Parameters.Add("X-Amz-Expires",AWS4PreSignedUrlSigner.MaxAWS4PreSignedUrlExpiry.ToString(CultureInfo.InvariantCulture));

            request.AuthenticationRegion = "us-east-1";
            request.AlternateEndpoint = RegionEndpoint.USEast1;
            request.UseSigV4 = true;
            request.Headers.Add("X-Amz-Security-Token",awsToken);
            request.Parameters.Add("X-Amz-Security-Token",awsToken);


            AWS4Signer signer = new AWS4Signer();
            Debug.Log ("a");
            signer.Sign(request,clientConfig,metrics,awsAccessKeyId,awsSecretAccessKey);
            var signerRes = signer.SignRequest(request,clientConfig,metrics,awsAccessKeyId,awsSecretAccessKey);
            Debug.Log ("b");
            var myParams =  string.Format("{0}&X-Amz-Security-Token={1}",signerRes.ForQueryParameters,awsToken);
            var dict = myParams.Split('&').Select(p=> p.Split('=')).GroupBy(p => p[0]).Select(p => p.First()).ToDictionary(p => p[0], p=>System.Uri.UnescapeDataString(p[1]));
            var myEncodedParams = string.Empty;
            bool isFirst = true;
            foreach (var key in dict.Keys) {
                myEncodedParams += string.Format("{0}{1}={2}",isFirst ? "" : "&",key,WWW.EscapeURL(dict[key]));
                isFirst = false;
            }

            var finalUrl = string.Format ("{0}?{1}", request.Endpoint.AbsoluteUri,myEncodedParams);

            UnityWebRequest uwr = new UnityWebRequest (finalUrl, "GET", new DownloadHandlerBuffer (), null);
            Debug.Log ( string.Format("\n\n\n{0}\n\n\n",finalUrl));
            Debug.Log ("Starting WebRequest");

            yield return uwr.Send();
            if (uwr.isError) {
                Debug.LogError (uwr.error);
            } else {
                Debug.Log (uwr.downloadHandler.text);   
            }

助手类:

public class ApiGatewayConfig : ClientConfig
    {
        private static readonly string UserAgentString =
            InternalSDKUtils.BuildUserAgentString("3.3.37.0");

        private string _userAgent = UserAgentString;


        public ApiGatewayConfig ()
        {
            this.AuthenticationServiceName = "execute-api";
        }


        /// <summary>
        /// The constant used to lookup in the region hash the endpoint.
        /// </summary>
        public override string RegionEndpointServiceName
        {
            get
            {
                return "execute-api";
            }
        }

        /// <summary>
        /// Gets the ServiceVersion property.
        /// </summary>
        public override string ServiceVersion
        {
            get
            {
                return "2015-07-09";
            }
        }

        /// <summary>
        /// Gets the value of UserAgent property.
        /// </summary>
        public override string UserAgent
        {
            get
            {
                return _userAgent;
            }
        }

    }

    public class MyRequest : AmazonWebServiceRequest
    {
        public MyRequest () {}
    }

【问题讨论】:

标签: unity3d aws-lambda aws-api-gateway facebook-unity-sdk


【解决方案1】:

已解决。

我创建了一些示例来展示如何做到这一点。仍在进行中,示例显示了如何签署从 Unity 3D 到具有“调用者凭据调用”(AWS_IAM) 的 Api 网关端点的 POST 请求。

Unity 3D 客户端:

https://github.com/guywald/serverless-auth-msg-board-unity3d-client

AWS 无服务器后端(使用 Serverless Framework):

https://github.com/guywald/serverless-auth-msg-board

【讨论】:

  • 感谢您分享@Guy!我正在为我的 Unity3d 游戏选择云提供商,并在考虑将 API Gateway 用于无服务器后端时遇到了您的帖子。到目前为止进展如何?您在调用 API Gateway 调用并在游戏后端整体使用 AWS 方面做得很好吗???很想知道!
  • 那么无服务器呢?没听说过,直到看到你的帖子。看起来很神奇。你的 Unity3d 集成怎么样?为什么不使用 API 网关?
  • 无服务器框架让您能够创建 AWS Api Gateway 终端节点并让它们调用 lambda 函数。使用此框架,可以更轻松地定义和部署它。还有其他工具,例如 SAM(无服务器应用程序模型)。这些工具将 Api 网关端点的定义(REST 的 url)和被调用的 lambda 放在定义 REST Api 的 JSON/YAML 中的相同位置。另一方面,您不需要带有 Api Gateway 的 REST Api 来访问 AWS 服务,这可以直接使用 AWS SDK 完成。
  • 感谢分享@Guy。您是否尝试过 Visual Studio serverless.template ? IT 似乎扮演了与无服务器相同的角色,但由 AWS 直接制造?
猜你喜欢
  • 1970-01-01
  • 2016-05-10
  • 2021-10-25
  • 2014-09-26
  • 2019-08-04
  • 2020-04-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多