0

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

4

1 回答 1

1

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

如果服务器接收到请求中包含的所有数据以及Authorization标头,并从Authorization标头中提取值(APP IdSignatureNonceRequest Time stamp),则客户端应该:

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

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

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

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

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();
}
于 2019-10-14T08:35:29.563 回答