.NET Blazor 9部署在Azure中如何捕获客户端IP地址?
解决方案:Azure托管.NET 9 Blazor InteractiveServer获取客户端IP
针对你遇到的Azure部署后HttpContext丢失、作用域服务异常初始化的问题,以下是两个可靠的实现方案:
方案1:通过SignalR连接上下文捕获IP
Blazor InteractiveServer基于SignalR通信,每个客户端连接对应独立的HubConnectionContext,可直接从中获取真实客户端IP,不受后续渲染周期影响。
- 创建IP存储的Scoped服务(InteractiveServer模式下Scoped绑定单个客户端连接):
public interface IClientIpStore { string ClientIp { get; set; } } public class ClientIpStore : IClientIpStore { public string ClientIp { get; set; } = string.Empty; }
- 实现SignalR Hub过滤器,在连接建立时捕获IP:
public class ClientIpCaptureFilter : IHubFilter { private readonly IClientIpStore _ipStore; public ClientIpCaptureFilter(IClientIpStore ipStore) { _ipStore = ipStore; } public async ValueTask<object?> InvokeMethodAsync(HubInvocationContext invocationContext, Func<HubInvocationContext, ValueTask<object?>> next) { // 仅首次连接时捕获IP if (string.IsNullOrEmpty(_ipStore.ClientIp)) { var httpContext = invocationContext.Context.GetHttpContext(); if (httpContext != null) { // 优先取Azure反向代理传递的真实客户端IP _ipStore.ClientIp = httpContext.Request.Headers["X-Forwarded-For"].FirstOrDefault() ?? httpContext.Connection.RemoteIpAddress?.ToString(); } } return await next(invocationContext); } }
- 在
Program.cs注册服务和过滤器:
builder.Services.AddScoped<IClientIpStore, ClientIpStore>(); builder.Services.AddSignalR(options => { options.AddFilter<ClientIpCaptureFilter>(); });
- 组件中注入使用:
@inject IClientIpStore IpStore <p>客户端IP:@IpStore.ClientIp</p>
方案2:初始请求时将IP存入Claims
利用首次HTTP请求的HttpContext将IP写入用户Claims,后续通过AuthenticationStateProvider读取,无需依赖HttpContext的持续存在。
- 自定义中间件处理初始请求:
public class ClientIpClaimsMiddleware { private readonly RequestDelegate _next; public ClientIpClaimsMiddleware(RequestDelegate next) { _next = next; } public async Task InvokeAsync(HttpContext context) { // 为匿名用户添加临时IP Claim if (!context.User.Identity?.IsAuthenticated ?? true) { string clientIp = context.Request.Headers["X-Forwarded-For"].FirstOrDefault() ?? context.Connection.RemoteIpAddress?.ToString(); if (!string.IsNullOrEmpty(clientIp)) { var identity = new ClaimsIdentity(new[] { new Claim("ClientIp", clientIp) }, "temp"); context.User = new ClaimsPrincipal(identity); } } await _next(context); } }
- 在
Program.cs注册中间件(放在Blazor Hub映射前):
app.UseMiddleware<ClientIpClaimsMiddleware>(); app.MapBlazorHub();
- 组件中读取Claims:
@inject AuthenticationStateProvider AuthStateProvider <p>客户端IP:@ClientIp</p> @code { private string ClientIp = "未知"; protected override async Task OnInitializedAsync() { var authState = await AuthStateProvider.GetAuthenticationStateAsync(); ClientIp = authState.User.FindFirst("ClientIp")?.Value ?? ClientIp; } }
关键配置:处理Azure反向代理
Azure部署时必须配置转发头,否则获取到的是代理服务器IP而非真实客户端IP,在Program.cs添加:
builder.Services.Configure<ForwardedHeadersOptions>(options => { options.ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto; // 允许Azure内部代理IP段 options.KnownProxies.Add(IPAddress.Parse("10.0.0.0/8")); options.KnownProxies.Add(IPAddress.Parse("100.64.0.0/10")); }); // 放在UseAuthentication之前执行 app.UseForwardedHeaders();
内容的提问来源于stack exchange,提问作者paultechguy
相关产品推荐
相关产品推荐

