【问题标题】:Why IHttpContextAccessor always get null IP in Blazor server-side?为什么 IHttpContextAccessor 总是在 Blazor 服务器端获得空 IP?
【发布时间】:2021-02-08 07:17:42
【问题描述】:

我使用的 SDK 是 5.0.100-rc.2.20479.15。

目标框架也是.Net 5。

这是我在 startup.cs 中的代码:

using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.HttpsPolicy;
using Microsoft.AspNetCore.Mvc.Infrastructure;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Threading.Tasks;

namespace Sample
{
    public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        public IConfiguration Configuration { get; }

        // This method gets called by the runtime. Use this method to add services to the container.
        // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddRazorPages();
            services.AddServerSideBlazor();            
            services.AddHttpContextAccessor();            
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            else
            {
                app.UseExceptionHandler("/Error");
            }

            app.UseStaticFiles();

            app.UseRouting();

            app.UseEndpoints(endpoints =>
            {
                endpoints.MapBlazorHub();
                endpoints.MapFallbackToPage("/_Host");
            });
        }
    }
}

这是我在 index.razor 中的代码:

@page "/"
@inject IHttpContextAccessor httpContextAccessor


<h1>@IP</h1>
@code{    
    public string IP{get;set;}
    protected override async Task OnAfterRenderAsync(bool firstRender)
    {
        if (firstRender)
        {
          IP=httpContextAccessor.HttpContext.Connection?.RemoteIpAddress.ToString();
        }
    }
}

我发布到服务器电脑,IP总是返回null。

我的程序需要提交一个表单。并且表格只允许同一个人每天提交一次(没有帐户)。

所以我需要获取 IP 并设置一个 IMemoryCache 和一天的 DateTimeOffset

尽管如此,存储 IP 地址并不是解决我的功能的完美方法,但似乎我只能这样做。

【问题讨论】:

    标签: asp.net-core .net-core blazor blazor-server-side


    【解决方案1】:

    Blazor 服务器应用程序的服务器端通过 SignalR 而不是 HTTP 与前端(浏览器)通信。因此,HttpContext 对象在 Blazor Server 应用程序中不可用,除非是对应用程序的初始请求,该请求始终是 HTTP 请求。这是您可以访问 HttpContext 的唯一机会。请注意,_Host.cshtml 文件是 Razor Page 文件,因此您可以在其中放置一些直接访问 HttpContext 的代码,并从 HttpContext 中获取您想要读取的任何数据,例如远程 IP 等。然后您可以将检索到的数据作为 _Host.cshtml 中存在的组件标记帮助程序的参数传递给 Blazor SPA。在 App 组件的 OnInitialized 生命周期方法中添加代码来获取数据,例如定义一个获取当前用户的远程 IP 地址的属性。然后,您可以将此数据存储在本地存储中以备后用

    【讨论】:

    • 我尝试在 startup.cs 中添加一个类来存储 IP 并使用 IHttpContextAccessor 获取 _Host.cshtml 中的 IP。但它仍然得到一个空 IP。
    • 问题解决了,我应该把它添加到 OnInitialized 中而不是 _Host.cshtml 中。
    【解决方案2】:

    警告:@enet 评论表明这不是在 Blazor 中解决此问题的推荐方法

    如果它可以帮助任何人......这是我对@Melon NG 建议的解释

    在_Host.cshtml.cs中

    using AutoCheck.BlazorApp.Components;
    using Microsoft.AspNetCore.Http;
    using Microsoft.AspNetCore.Mvc.RazorPages;
    
    
    namespace AutoCheck.BlazorApp.Pages
    {
        public class Host : PageModel
        {
            private readonly IHttpContextAccessor _httpContextAccessor;
            private readonly IRememberMe _rememberMe;
    
            public Host(IHttpContextAccessor httpContextAccessor, IRememberMe rememberMe)
            {
                _rememberMe = rememberMe;
                _httpContextAccessor = httpContextAccessor;
            }
    
            public void OnGet()
            {
                _rememberMe.RemoteIpAddress = _httpContextAccessor.HttpContext.Connection.RemoteIpAddress;
                
            }
        }
    }
    

    记住我

    using System.Net;
    
    namespace AutoCheck.BlazorApp.Components
    {
        public interface IRememberMe
        {
            public IPAddress RemoteIpAddress { get; set; }
        }
    
        public class RememberMe : IRememberMe
        {
            public IPAddress RemoteIpAddress { get; set; }
        }
    }
    

    关于.razor

    @page "/About"
    @inject IRememberMe RememberMe
    
    
    <h3>About</h3>
    
    <table class="table table-striped">
        <thead>
        <td>Item</td>
        <td>Value</td>
        </thead>
     
        <tr>
            <td>Remote IP</td>
            <td>@RememberMe.RemoteIpAddress</td>
        </tr>
        
    </table>
    
    

    在 Startup.cs 的 ConfigureServices 中

    public void ConfigureServices(IServiceCollection services)
    {
    ...
    //services.AddSingleton<IRememberMe, RememberMe>();
    services.AddScoped<IRememberMe, RememberMe>();
    ...
    }
    

    【讨论】:

    • 你为什么要注入 IHttpContextAccessor ?当您可以直接访问 HttpContext 时,为什么需要它?所以,你已经为此创建了一个单例服务,对吧?您要为所有用户提供相同的 IP 地址吗?这不是将参数传递给 Blazor 应用程序的方法。在文档中查看正确的方法:docs.microsoft.com/en-us/aspnet/core/fundamentals/…
    • @Melon NG,请再次阅读您的问题:Why IHttpContextAccessor always get null IP in Blazor server-side?
    • 正如@enet 正确指出的那样,它应该是 services.AddScoped();以便捕获每个用户的 IP 地址。然而,正如链接所暗示的那样,这可能从根本上不是正确的方法。由于我不确定此处的正确礼仪,我将更新答案以包含对此的警告。如果我应该做其他事情,请告诉我。
    猜你喜欢
    • 2012-07-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-05
    • 1970-01-01
    • 1970-01-01
    • 2021-07-03
    • 1970-01-01
    相关资源
    最近更新 更多