代码之家  ›  专栏  ›  技术社区  ›  Gforse

在HttpWebRequestMessage中找不到正文

  •  0
  • Gforse  · 技术社区  · 5 年前

    目前,我正在使用Microsoft OData连接服务通过HMAC控制WebAPI。到目前为止,我设法让方法发挥作用。然而,当我发布消息时,我需要散列原始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
    
    0 回复  |  直到 5 年前
        1
  •  0
  •   unchase    5 年前

    目前,我不知道该怎么做。除非在调用之前以某种方式接收请求正文,并将其放入 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,而不需要请求主体。