如何在 Blazor 中获取客户端 IP 和浏览器信息?

jsm*_*ars 10 blazor blazor-server-side

如何在 Blazor 服务器端获取客户端信息,例如 IP 地址和浏览器名称/版本?

Dan*_*ano 10

好吧,我今天早上遇到了这个问题,我为服务器端 Blazor 解决这个问题的方法是创建一个类,然后您可以将其作为范围服务注入 _host.cshtml,然后在您的 Blazor 组件上的任何位置访问它,因为 Razor 页面已经对此提供了支持。

    public class BlazorAppContext
    {
        /// <summary>
        /// The IP for the current session
        /// </summary>
        public string CurrentUserIP { get; set; }
    }
Run Code Online (Sandbox Code Playgroud)

启动.cs:

    // This method gets called by the runtime. Use this method to add services to the container.
    public void ConfigureServices(IServiceCollection services)
    {
      ...

      services.AddScoped<BlazorAppContext>();

      ...
    }
Run Code Online (Sandbox Code Playgroud)

_host.cshtml:

@inject IHttpContextAccessor httpContextAccessor
@{
    BlazorAppContext.CurrentUserIP =   httpContextAccessor.HttpContext.Connection?.RemoteIpAddress.ToString();
}
Run Code Online (Sandbox Code Playgroud)

您还可以尝试 Scoped 方法,然后可以通过 DI 使用该方法。

注解:

如文档中所述,“Blazor WebAssembly 应用程序目前没有 DI 范围的概念。范围注册服务的行为类似于单例服务。但是,Blazor 服务器托管模型支持范围生命周期。在 Blazor 服务器应用程序中,范围服务注册的范围仅限于连接。因此,即使当前的意图是在浏览器中运行客户端,对于应将范围限定为当前用户的服务,首选使用范围服务。”

我希望它有帮助。

  • “静态”字段如何处理多个用户? (2认同)

Gre*_*Gum 8

这是为了澄清有关如何在 Blazor 服务器中获取用户的远程 AP 地址的现有已接受答案。您可能认为这很容易,但由于 Blazor 服务器在 ASP.NET Core 应用程序的正常上下文之外运行,因此存在复杂性。

因此,不建议在 Blazor 组件中直接使用 HttpContextAccess 。因此,即使看起来您可以轻松地在组件中访问它,您也不应该这样做。

推荐的方法是在 _host.cshtml 中使用 HttpAccessor(可以使用它),然后将此信息传递给 app.razor,然后 app.razor 可以通过级联参数将其传递给应用程序的其余部分,或者通过更新范围依赖项。

这是使用范围依赖项的示例:

将用作作用域依赖项的类:

public class BlazorAppContext
{
    /// <summary>
    /// The IP for the current session
    /// </summary>
    public string CurrentUserIP { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

添加到Program.cs

  builder.Services.AddScoped<BlazorAppContext>();
  builder.Services.AddHttpContextAccessor()
Run Code Online (Sandbox Code Playgroud)

更新 _host.cshtml 如下:

 @inject IHttpContextAccessor httpContextAccessor;
 @{
     var remoteIpAddress = 
    httpContextAccessor.HttpContext.Connection?.RemoteIpAddress.ToString();
  }

 ...
 <component type="typeof(App)" param-RemoteIpAddress=remoteIpAddress 
 render-mode="Server" />
Run Code Online (Sandbox Code Playgroud)

现在更新App.razor

[Parameter]
public string? RemoteIpAddress { get; set; }

[Inject]
BlazorAppContext BlazorAppContext { get; set; }

protected override async Task OnInitializedAsync()
{
    this.BlazorAppContext.CurrentUserIP = this.RemoteIpAddress;
}
Run Code Online (Sandbox Code Playgroud)

应用程序现已设置完毕,以便 BlazorAppContext 将拥有正确的 IP 地址或通过注入需要它的任何组件。


Kon*_*cki 7

下面介绍了如何在 2021 年 .NET 5 的服务器端 Blazor 中执行此操作。

请注意,我的解决方案只会为您提供 IP 地址,但使用我的解决方案应该可以轻松获取用户代理。

我将复制此处提供的博客文章的内容:https://bartecki.me/blog/Blazor-serverside-get-remote-ip

总而言之:

您可以使用 JavaScript 调用您自己的公开端点,该端点将使用以下代码返回远程连接 IP:

RemoteIpAddress = Request.HttpContext.Connection.RemoteIpAddress.ToString() 
Run Code Online (Sandbox Code Playgroud)

...缺点是必须处理您的反向代理服务器(如果有的话),否则您只会获得反向代理的 IP 地址。

或者,您可以使用 JavaScript 调用外部端点,该端点将为您返回 IP 地址,但缺点是您必须配置 CORS,即使如此,它也可能被某些广告拦截扩展程序阻止。

细节:

两种方法

方法一:使用JavaScript调用外部服务

优点:

  • 如果您使用反向代理(例如 nginx、traefik),则稍微简单一些

缺点:

  • 可能被外部扩展程序/广告拦截器阻止
  • 您必须配置 CORS
_Host.cshtml
<script>
  window.getIpAddress = () => {
    return fetch('https://jsonip.com/')
      .then((response) => response.json())
      .then((data) => {
        return data.ip
      })
  }
</script>
Run Code Online (Sandbox Code Playgroud) RazorPage.razor.cs
    public partial class RazorPage : ComponentBase
    {
        [Inject] public IJSRuntime jsRuntime { get; set; }

        public async Task<string> GetIpAddress()
        {
            try
            {
                var ipAddress = await jsRuntime.InvokeAsync<string>("getIpAddress")
                    .ConfigureAwait(true);
                return ipAddress;
            }
            catch(Exception e)
            {
                //If your request was blocked by CORS or some extension like uBlock Origin then you will get an exception.
                return string.Empty;
            }
        }
    }
Run Code Online (Sandbox Code Playgroud) Startup.cs
        public void ConfigureServices(IServiceCollection services)
        {
            //code...
            services
                .AddCors(x => x.AddPolicy("externalRequests",
                    policy => policy
                .WithOrigins("https://jsonip.com")));
        }

        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            //code...
            app.UseCors("externalRequests");
        }
Run Code Online (Sandbox Code Playgroud)

方法 2:在 Blazor 应用程序中公开端点并使用 JavaScript 调用它

优点:

  • 您无需配置 CORS
  • 不会被扩展程序或广告拦截器阻止

缺点:

  • 如果您使用 nginx、traefik 等反向代理,可能会稍微复杂一些。

现在请小心,因为您将使用此方法,因为如果您使用反向代理,那么您实际上会收到反向代理 IP 地址。您的反向代理很可能已经在某种标头中转发外部客户端的 IP 地址,但这取决于您自己来解决。

示例: https: //www.nginx.com/resources/wiki/start/topics/examples/forwarded/

InfoController.cs
    [Route("api/[controller]")]
    [ApiController]
    public class InfoController : ControllerBase
    {
        [HttpGet]
        [Route("ipaddress")]
        public async Task<string> GetIpAddress()
        {
            var remoteIpAddress = this.HttpContext.Request.HttpContext.Connection.RemoteIpAddress;
            if (remoteIpAddress != null)
                return remoteIpAddress.ToString();
            return string.Empty;
        }
    }
Run Code Online (Sandbox Code Playgroud) Startup.cs
            app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllers(); //remember to map controllers if you don't have this line
                endpoints.MapBlazorHub();
                endpoints.MapFallbackToPage("/_Host");
            });
Run Code Online (Sandbox Code Playgroud) _Host.cshtml
<script>
  window.getIpAddress = () => {
    return fetch('/api/info/ipaddress')
      .then((response) => response.text())
      .then((data) => {
        return data
      })
  }
</script>
Run Code Online (Sandbox Code Playgroud) RazorPage.razor.cs
    public partial class RazorPage : ComponentBase
    {
        [Inject] public IJSRuntime jsRuntime { get; set; }

        public async Task<string> GetIpAddress()
        {
            try
            {
                var ipAddress = await jsRuntime.InvokeAsync<string>("getIpAddress")
                    .ConfigureAwait(true);
                return ipAddress;
            }
            catch(Exception e)
            {
                //If your request was blocked by CORS or some extension like uBlock Origin then you will get an exception.
                return string.Empty;
            }
        }
    }
Run Code Online (Sandbox Code Playgroud)


Dmi*_*try 5

在 aspnetcore3.1 这对我有用:

  1. 制作特殊类以保存所需信息:
public class ConnectionInfo
{
    public string RemoteIpAddress { get; set; } = "-none-";
}
Run Code Online (Sandbox Code Playgroud)
  1. 在其中创建实例_Host.cshtmlApp作为参数传递给组件:
@{
    var connectionInfo = new ConnectionInfo() 
    { 
        RemoteIpAddress = Request.HttpContext.Connection.RemoteIpAddress.ToString() 
    };
}
...
<component type="typeof(App)" 
           render-mode="ServerPrerendered"
           param-ConnectionInfo="connectionInfo" />
Run Code Online (Sandbox Code Playgroud)
  1. App.razor捕获并重新发布为CascadingValue
<CascadingValue Value="connectionInfo">
  <Router AppAssembly="typeof(Program).Assembly">
      ...
  </Router>
</CascadingValue>

@code {
    [Parameter]
    public ConnectionInfo? connectionInfo { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
  1. 在任何子页面/组件中获取为CascadingParameter
@code {
    [CascadingParameter]
    private ConnectionInfo? connectionInfo { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

这里唯一的问题是漫游用户 - 当用户更改他的 IP 地址并且 Blazor 没有“捕获”这个(例如后台的浏览器选项卡)时,您将拥有旧的 IP 地址,直到用户刷新 (F5) 页面。


Sir*_*ire 1

请注意,这仅指服务器端 Blazor

“目前没有好的方法可以做到这一点。我们将研究如何向客户提供这些信息。”

来源:Github 上的 Blazor 开发人员

解决方法

客户端向服务器发出 ajax 调用,然后服务器可以获取本地 IP 号码。JavaScript:

window.GetIP = function () {
    var token = $('input[name="__RequestVerificationToken"]').val();
    var myData = {}; //if you want to post extra data
    var dataWithAntiforgeryToken = $.extend(myData, { '__RequestVerificationToken': token });
    var ip = String('');
    $.ajax({
        async: !1, //async works as well 
        url: "/api/sampledata/getip",
        type: "POST",
        data: dataWithAntiforgeryToken,
        success: function (data) {
            ip = data;
            console.log('Got IP: ' + ip);
        },
        error: function () {
            console.log('Failed to get IP!');
        }
    });
    return ip;
};
Run Code Online (Sandbox Code Playgroud)

后端(ASP.NET Core 3.0):

    [HttpPost("[action]")]
    [AllowAnonymous]
    [ValidateAntiForgeryToken]
    public string GetIP()
    {
        return HttpContext.Connection.RemoteIpAddress?.ToString();
    }
Run Code Online (Sandbox Code Playgroud)

请注意,这并不安全,IP 号码可能会被欺骗,因此请勿用于任何重要的用途。