已在 C# API 中解决。对于将它用作控制器的 C# API 中的属性的人,我在 StackOverflow 上使用多个线程制定了一个很好的解决方案:
[AttributeUsage(AttributeTargets.Method)]
public class ShaKeyAttribute : Attribute, IAuthorizationFilter
{
private readonly ShaAuthOptions _options;
private readonly ILogger<ShaKeyAttribute> _log;
public ShaKeyAttribute(IOptions<ShaAuthOptions> options, ILogger<ShaKeyAttribute> log)
{
this._options = options.Value;
this._log = log;
}
public void OnAuthorization(AuthorizationFilterContext context)
{
this._log.LogInformation("Entering in Sha Auth...");
if (!context.HttpContext.Request.Headers.TryGetValue("x-wc-webhook-signature", out var extractedSignature))
{
this._log.LogError("Sha Auth failed. Signature was not provided");
context.Result = new ContentResult()
{
StatusCode = 401,
Content = "Signature was not provided",
};
return;
}
// This logic for body rewind comes from: https://stackoverflow.com/a/40994711/14010438
string bodyString;
var req = context.HttpContext.Request;
// Allows using several time the stream in ASP.Net Core
req.EnableBuffering();
// Arguments: Stream, Encoding, detect encoding, buffer size
// AND, the most important: keep stream opened
using (StreamReader reader
= new StreamReader(req.Body, Encoding.UTF8, true, 1024, true))
{
bodyString = reader.ReadToEnd();
}
// Rewind, so the core is not lost when it looks the body for the request
req.Body.Position = 0;
// From this point, DON'T TOUCH THE REQUEST BODY. Instead, use bodyString
// https://stackoverflow.com/a/62032738/14010438
byte[] requestData = Encoding.UTF8.GetBytes(bodyString);
var encoding = new UTF8Encoding();
var key = this._options.Secret;
var keyBytes = encoding.GetBytes(key);
var hash = new HMACSHA256(keyBytes);
var computedHash = hash.ComputeHash(requestData);
var computedHashString = Convert.ToBase64String(computedHash);
if (extractedSignature != computedHashString)
{
this._log.LogError("Sha Auth failed. Signature is not valid");
context.Result = new ContentResult()
{
StatusCode = 401,
Content = "Signature is not valid",
};
}
this._log.LogInformation("Successfully passed Sha Auth.");
}
}
你还需要在你的 startup.cs 中添加这个:
// https://stackoverflow.com/questions/47735133/asp-net-core-synchronous-operations-are-disallowed-call-writeasync-or-set-all
// Needed for ShaAuth
services.Configure<KestrelServerOptions>(options =>
{
options.AllowSynchronousIO = true;
});
这是我的控制器:
[AllowAnonymous]
[HttpPost]
[ServiceFilter(typeof(ShaKeyAttribute))]
public async Task<IActionResult> Create([FromBody] WooCommerceRequest request)
{
this._log.LogInformation("Executing Create of Subscription controller...");
var response = await this._mediator.Send(new AddSubscriptionCommand() { OrderId = request.OrderId });
this._log.LogInformation("Finished executing Create of Subscription controller.");
return this.Ok();
}
希望这对某人有所帮助。