.NET Core MVC中Stripe WebHook触发403错误,如何配置IP白名单?
问题
支付流程完成后,Stripe WebHook端点触发时返回403 Forbidden错误。已在IIS中配置允许Stripe的IP地址,但问题依旧。当前.NET Core MVC的WebHook代码逻辑无异常,需要实现类似经典ASP.NET MVC中<system.web>下ipSecurity的IP白名单功能,仅允许Stripe API指定IP访问该端点。
现有代码
.NET Core MVC WebHook 代码
[HttpPost] public async Task<IActionResult> AfterPayment() { const string endpointSecret = "whsec*****************"; var json = await new StreamReader(HttpContext.Request.Body).ReadToEndAsync(); try { var stripeEvent = EventUtility.ConstructEvent(json, Request.Headers["Stripe-Signature"], endpointSecret); // 处理事件 if (stripeEvent.Type == Events.CheckoutSessionAsyncPaymentSucceeded) { // 业务处理逻辑 } // 注意:需补充返回Ok()等响应,避免请求挂起 } catch (Exception) { return BadRequest(); } }
经典ASP.NET MVC IP配置示例
<system.web> <security> <ipSecurity> <add ipAddress="x.x.x.x" allowed="true" /> <!-- 其他IP配置 --> </ipSecurity> </security> </system.web>
解决方案
在.NET Core MVC中实现IP白名单有以下几种可行方式:
1. 自定义Action过滤器
创建过滤器,在动作执行前验证请求IP:
public class IpWhitelistAttribute : ActionFilterAttribute { public string[] AllowedIps { get; set; } public override void OnActionExecuting(ActionExecutingContext context) { var remoteIp = context.HttpContext.Connection.RemoteIpAddress?.ToString(); if (AllowedIps == null || !AllowedIps.Contains(remoteIp)) { context.Result = new ForbidResult(); return; } base.OnActionExecuting(context); } }
直接在WebHook动作上应用该过滤器:
[HttpPost] [IpWhitelist(AllowedIps = new[] { "1.2.3.4", "5.6.7.8" })] // 替换为Stripe的实际IP/IP段 public async Task<IActionResult> AfterPayment() { // 原代码逻辑 }
2. 局部中间件
针对WebHook端点单独配置中间件验证IP:
public class IpRestrictionMiddleware { private readonly RequestDelegate _next; private readonly HashSet<string> _allowedIps; public IpRestrictionMiddleware(RequestDelegate next, IEnumerable<string> allowedIps) { _next = next; _allowedIps = new HashSet<string>(allowedIps); } public async Task InvokeAsync(HttpContext context) { var remoteIp = context.Connection.RemoteIpAddress?.ToString(); if (!_allowedIps.Contains(remoteIp)) { context.Response.StatusCode = StatusCodes.Status403Forbidden; await context.Response.WriteAsync("Forbidden: IP not allowed"); return; } await _next(context); } } // 扩展方法 public static IApplicationBuilder UseIpRestriction(this IApplicationBuilder app, IEnumerable<string> allowedIps) { return app.UseMiddleware<IpRestrictionMiddleware>(allowedIps); }
在Program.cs中为WebHook端点映射中间件:
var stripeIps = new List<string> { "1.2.3.4", "5.6.7.8" }; // Stripe的IP列表 app.MapPost("/YourController/AfterPayment", appBuilder => { appBuilder.UseIpRestriction(stripeIps); appBuilder.Run(async context => { // 委托到控制器动作 var invoker = context.RequestServices.GetRequiredService<IActionInvokerFactory>() .CreateInvoker(new ControllerActionDescriptor { ControllerTypeInfo = typeof(YourController).GetTypeInfo(), ActionName = nameof(YourController.AfterPayment) }); await invoker.InvokeAsync(); }); });
3. IIS Web.config配置
.NET Core不依赖经典ASP.NET的<system.web>节点,需在web.config的<system.webServer>下配置IP限制:
<system.webServer> <security> <ipSecurity allowUnlisted="false"> <add ipAddress="1.2.3.4" allowed="true" /> <!-- Stripe单IP --> <add ipAddress="5.6.7.0" subnetMask="255.255.255.0" allowed="true" /> <!-- Stripe IP段示例 --> </ipSecurity> </security> </system.webServer>
前提是IIS已安装IP and Domain Restrictions模块,且站点应用池配置正确。
注意事项
- Stripe的WebHook IP地址可从官方文档获取,部分场景下Stripe使用IP段,需配置对应的CIDR格式地址。
- 除IP白名单外,务必保留Stripe签名验证逻辑(代码中已实现),这是防御伪造请求的核心手段。
内容的提问来源于stack exchange,提问作者Ömer Akkuş
相关产品推荐
相关产品推荐

