using LifePayment.Domain.Shared; using Microsoft.AspNetCore.Authentication; using Microsoft.AspNetCore.Http; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using Microsoft.Extensions.Primitives; using System.Security.Authentication; using System.Security.Claims; using System.Text; using System.Text.Encodings.Web; using System.Threading.Tasks; namespace LifePayment.Domain { public class WxPayAuthenticationHandler : AuthenticationHandler { private readonly WxPayRsaHelper _wxPayRsaHelper; public WxPayAuthenticationHandler( IOptionsMonitor options, ILoggerFactory logger, UrlEncoder encoder, ISystemClock clock, WxPayRsaHelper wxPayRsaHelper) : base(options, logger, encoder, clock) { _wxPayRsaHelper = wxPayRsaHelper; } protected async override Task HandleAuthenticateAsync() { StringValues signature; StringValues wechatpayNonce; StringValues timespan; var exist = Request.Headers.TryGetValue("Wechatpay-Signature", out signature); if (!exist) { return AuthenticateResult.Fail("Wechatpay-Signature 404"); } var wechatpayNonceExist = Request.Headers.TryGetValue("Wechatpay-Nonce", out wechatpayNonce); if (!wechatpayNonceExist) { return AuthenticateResult.Fail("Wechatpay-Nonce 404"); } var timespanExist = Request.Headers.TryGetValue("Wechatpay-Timestamp", out timespan); if (!timespanExist) { return AuthenticateResult.Fail("Wechatpay-Timestamp 404"); } Request.EnableBuffering(); var bytes = new byte[Request.ContentLength ?? 0]; var bt = 1; while (bt > 0) { bt = await Request.Body.ReadAsync(bytes, 0, (int)(Request.ContentLength ?? 0)); } var str = Encoding.Default.GetString(bytes); Request.Body.Position = 0; var mySign = BuildAuth(timespan.ToString(), wechatpayNonce.ToString(), str); var check = _wxPayRsaHelper.Verify(mySign, signature.ToString()); if (check) { var claimIdentity = new ClaimsIdentity("WxPayIdentity"); var principal = new ClaimsPrincipal(claimIdentity); return AuthenticateResult.Success(new AuthenticationTicket(principal, WxPaySignAuthenticationDefaults.AuthenticationScheme)); } else { return AuthenticateResult.Fail(new AuthenticationException("验签失败")); } } private string BuildAuth(string timeSpan, string nonce, string body) { var str = $"{timeSpan}\n{nonce}\n{body}\n"; return str; } } }