目前,我不知道这样做的正确方法。除非在调用之前以某种方式接收请求的主体,并将其放入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。