Не удается найти тело в HttpWebRequestMessage - PullRequest
0 голосов
/ 11 октября 2019

В настоящее время я использую службу Microsoft OData, связанную для управления WebAPI с HMAC. Пока мне удалось заставить работать методы GET. Однако, когда я отправляю сообщение, мне нужно хэшировать необработанное тело HTTP и добавить его в заголовок. (из-за подписи HMAC)

Пока я получил:

Private WebCon As New Container(New Uri("http://domain/odata/v1"))

WebCon.Configurations.RequestPipeline.OnMessageCreating = Function(args)
                                                                  Dim request As New HttpWebRequestMessage(args)


                                                                  'Todo hash content if there is any
                                                                  Dim contentMd5Hash As String = ""

                                                                  If args.Method = "POST" Then
                                                                      'Todo, retrieve raw (JSON) content from the HttpWebRequestMessage so i can do make a MD5 hash of it.
                                                                  End If

                                                                  'rest of code thath creates the headers.
                                                               End function

1 Ответ

0 голосов
/ 14 ноября 2019

В данный момент я не знаю, как правильно это сделать. Если только каким-то образом не получить тело запроса перед вызовом и поместить его в container.Configurations.RequestPipeline.OnMessageCreating:

[Route("api/[controller]")]
[ApiController]
public class ValuesController : ControllerBase
{
    // POST api/values/5
    [HttpPost("{id}")]
    public async Task PostAction(int id, [FromBody] string value)
    {
        var container = new DefaultContainer(new Uri("https://services.odata.org/V4/(S(qc322lduoxrqt13nhydbdcvx))/TripPinServiceRW/"));

        // You need to get request body for HMAC
        var postData = new
        {
            Id = id,
            Value = value
        };
        byte[] requestBody = await new ObjectContent(typeof(object), postData, new JsonMediaTypeFormatter()).ReadAsByteArrayAsync();

        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("N");

            // Get request body for not GET requests (with Microsoft.AspNetCore.Http.HttpRequest Request.Body)
            var requestContentBase64String = string.Empty;
            if (!request.Method.Equals("GET", StringComparison.OrdinalIgnoreCase) && requestBody != null && requestBody.Length != 0)
            {
                var md5 = MD5.Create();
                var requestContentHash = md5.ComputeHash(requestBody);
                requestContentBase64String = Convert.ToBase64String(requestContentHash);
            }

            // 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}{5}", APPId, request.Method, requestUri, requestTimeStamp, nonce, requestContentBase64String);

            // 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 (var 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));

                // You can add more haeder you need there
            }

            return request;
        };

        // Call some OData method with postData
        var result = container.CallSomeMethod(postData);

        // Add more business logic there

    }
}

Можно ли изменить логику сервера, чтобы избежать тела запроса в заголовке авторизации HMAC? Затем вы можете использовать HMAC без тела запроса на стороне клиента.

...