【问题标题】:Use HMAC with OData Connected Service将 HMAC 与 OData 连接服务一起使用
【发布时间】:2019-10-01 20:37:43
【问题描述】:

所以我们想使用一个在 ASP.net 中构建并使用 OData 作为协议的 webapi。我做了一些功课,发现微软有一个非常好的文档OData Connected Service。我唯一找不到的是我们要使用的 webapi 具有 HMAC 以确保安全。我找不到 OData Connected Service 与 HMAC 一起使用的示例。有人可以解释一下OData Connected Service 是否以及如何实现 HMAC?

【问题讨论】:

    标签: wpf oauth odata hmac odata-connected-service


    【解决方案1】:

    可能答案取决于服务器端 HMAC 的具体实现。

    如果服务器接收到请求中包含的所有数据以及 Authorization 标头并提取值(APP IdSignature、Nonce 和 Request Time stamp) 来自 Authorization 标头,那么客户端应该:

    • 通过组合所有将要发送的数据构建一个字符串,该字符串包含以下参数(APP IdHTTP方法request URI请求时间戳nonce请求有效负载的Base 64字符串表示)。

    • 签名将使用自定义方案(例如“amx”)在 Authorization 标头中发送。 Authorization 标头中的数据将包含 APP Id请求时间戳nonce,以冒号“:”分隔。 Authorization 标头的格式如下:[Authorization: amx APPId:Signature:Nonce:Timestamp].

    • 客户端像往常一样发送请求以及 Authorization 标头中生成的数据(只需使用client hookshttpclient)。

    示例(生成客户端代码后):

    private string APPId = "65d3a4f0-0239-404c-8394-21b94ff50604";
    private string APIKey = "WLUEWeL3so2hdHhHM5ZYnvzsOUBzSGH4+T3EgrQ91KI=";
    
    public async Task<IEnumerable<string>> TestODataHMAC()
    {
        // add there your OData Uri
        var container = new DefaultContainer(new Uri("https://services.odata.org/V4/(S(qc322lduoxrqt13nhydbdcvx))/TripPinServiceRW/")); 
        container.Configurations.RequestPipeline.OnMessageCreating = (args) =>
        {
            var request = new HttpWebRequestMessage(args);
    
            // Get the Request URI
            string requestUri = HttpUtility.UrlEncode(request.Url.AbsoluteUri.ToLower());
    
            // Calculate UNIX time
            var epochStart = new DateTime(1970, 01, 01, 0, 0, 0, 0, DateTimeKind.Utc);
            var timeSpan = DateTime.UtcNow - epochStart;
            var requestTimeStamp = Convert.ToUInt64(timeSpan.TotalSeconds).ToString();
    
            // Create the random nonce for each request
            var nonce = Guid.NewGuid().ToString();
    
            // Creating the raw signature string by combinging
            // APPId, request Http Method, request Uri, request TimeStamp, nonce
            var signatureRawData = string.Format("{0}{1}{2}{3}{4}", APPId, request.Method, requestUri, requestTimeStamp, nonce);
    
            // Converting the APIKey into byte array
            var secretKeyByteArray = Convert.FromBase64String(APIKey);
    
            // Converting the signatureRawData into byte array
            var signature = Encoding.UTF8.GetBytes(signatureRawData);
    
            // Generate the hmac signature and set it in the Authorization header
            using (HMACSHA256 hmac = new HMACSHA256(secretKeyByteArray))
            {
                var signatureBytes = hmac.ComputeHash(signature);
                var requestSignatureBase64String = Convert.ToBase64String(signatureBytes);
    
                //Setting the values in the Authorization header using custom scheme (hmacauth)
                request.SetHeader("Authorization", string.Format("hmacauth {0}:{1}:{2}:{3}", APPId, requestSignatureBase64String, nonce, requestTimeStamp));
            }
    
            return request;
        };
    
        // add there your OData method call 
        var nquery = container.People.Where(p => p.Gender == PersonGender.Female).Take(10) as DataServiceQuery<Person>;
        var response = await nquery?.ExecuteAsync();
        return (response as QueryOperationResponse<Person>).Select(p => p.FirstName).ToArray();
    }
    

    【讨论】:

    • 感谢您的回复!在这种情况下,还请求内容的 MD5 HASH,那么如何对 OnMessageCreating 中的内容/正文进行 HASH ?
    • 目前,我不知道执行此操作的正确方法。除非在调用之前以某种方式接收请求的正文,并将其放入container.Configurations.RequestPipeline.OnMessageCreating。您可以更改服务器逻辑以避免 HMAC 授权标头中的请求正文吗?然后您可以在客户端使用没有请求正文的 HMAC。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-07-13
    • 2011-09-05
    • 2020-01-21
    • 1970-01-01
    相关资源
    最近更新 更多