如何在 Blazor 中获取客户端 IP 和浏览器信息?
How do I get client IP and browser info in Blazor?
如何在 Blazor 服务器端获取 IP 地址和浏览器等客户端信息name/version?
请注意,这仅指服务器端 Blazor。
"There is no a good way to do this at the moment. We will look into
how we can provide make this information available to the client."
解决方法
客户端向服务器发出 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;
};
后端(ASP.NET Core 3.0):
[HttpPost("[action]")]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public string GetIP()
{
return HttpContext.Connection.RemoteIpAddress?.ToString();
}
请注意,这并不安全,ip 号码可能会被欺骗,所以不要用于任何重要的事情。
好吧,我今天早上遇到了这个问题,我为服务器端 Blazor 解决它的方法是创建一个 class,然后您可以将其作为作用域服务注入 _host.cshtml ,然后在您的 Blazor 组件上的任何位置访问它,因为 Razor 页面已经支持它。
public class BlazorAppContext
{
/// <summary>
/// The IP for the current session
/// </summary>
public string CurrentUserIP { get; set; }
}
Startup.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>();
...
}
_host.cshtml:
@inject IHttpContextAccessor httpContextAccessor
@{
BlazorAppContext.CurrentUserIP = httpContextAccessor.HttpContext.Connection?.RemoteIpAddress.ToString();
}
您也可以尝试通过 DI 使用 Scoped 方法。
注解:
如文档中所述,“Blazor WebAssembly 应用目前没有 DI 范围的概念。范围注册服务的行为类似于单例服务。但是,Blazor 服务器托管模型支持范围生命周期。在 Blazor 服务器中应用程序,范围服务注册的范围是连接。因此,对于应该范围为当前用户的服务,最好使用范围服务,即使当前意图是 运行 中的客户端浏览器。"
希望对您有所帮助。
在 aspnetcore3.1 中,这对我有用:
- 制作特殊 class 以保存所需信息:
public class ConnectionInfo
{
public string RemoteIpAddress { get; set; } = "-none-";
}
- 在
_Host.cshtml
中创建实例并作为参数传递给 App
组件:
@{
var connectionInfo = new ConnectionInfo()
{
RemoteIpAddress = Request.HttpContext.Connection.RemoteIpAddress.ToString()
};
}
...
<component type="typeof(App)"
render-mode="ServerPrerendered"
param-ConnectionInfo="connectionInfo" />
- 在
App.razor
中捕获并 re-publish 为 CascadingValue
:
<CascadingValue Value="connectionInfo">
<Router AppAssembly="typeof(Program).Assembly">
...
</Router>
</CascadingValue>
@code {
[Parameter]
public ConnectionInfo? connectionInfo { get; set; }
}
- 在任何 child page/component 中获得
CascadingParameter
:
@code {
[CascadingParameter]
private ConnectionInfo? connectionInfo { get; set; }
}
这里唯一的问题是漫游用户 - 当用户更改他的 IP 地址并且 Blazor 没有“捕获”这个(例如后台的浏览器选项卡)时,您将拥有旧的 IP 地址,直到用户刷新 (F5) 页面。
以下是 2021 年在服务器端 Blazor for .NET 5 中的操作方法。
请注意,我的解决方案只会为您提供一个 IP 地址,但使用我的解决方案获取用户代理应该很容易。
我将只复制我的博客 post 的内容:https://bartecki.me/blog/Blazor-serverside-get-remote-ip
TLDR:
您可以使用 JavaScript 调用您自己公开的端点,该端点将 return 使用以下代码远程连接 IP:
RemoteIpAddress = Request.HttpContext.Connection.RemoteIpAddress.ToString()
...缺点是必须处理您的反向代理服务器(如果有的话),否则您只会获得反向代理的 IP 地址。
或者您可以使用 JavaScript 调用外部端点,这将为您 return 一个 IP 地址,但缺点是您必须配置 CORS,即使这样它也可能被某些广告拦截程序阻止扩展。
详情:
两种方法
方法一:使用JavaScript
调用外部服务
优点:
- 如果你使用nginx、traefik等反向代理,会稍微简单一些
缺点:
- 可能被外部阻止extensions/adblockers
- 您将必须配置 CORS
_Host.cshtml
<script>
window.getIpAddress = () => {
return fetch('https://jsonip.com/')
.then((response) => response.json())
.then((data) => {
return data.ip
})
}
</script>
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;
}
}
}
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");
}
方法 2:在我们的 Blazor 应用程序中公开一个端点并使用 JavaScript
调用它
优点:
- 您不必配置 CORS
- 不会被扩展程序或广告拦截器阻止
缺点:
- 如果您使用反向代理,如 nginx、traefik 等,可能会稍微复杂一些
现在要小心,因为您将使用这种方法,因为如果您使用反向代理,那么您实际上会收到反向代理 IP 地址。
很可能您的反向代理已经在以某种方式转发外部客户端的 IP 地址 header,但这取决于您自己想办法。
示例: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;
}
}
Startup.cs
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers(); //remember to map controllers if you don't have this line
endpoints.MapBlazorHub();
endpoints.MapFallbackToPage("/_Host");
});
_Host.cshtml
<script>
window.getIpAddress = () => {
return fetch('/api/info/ipaddress')
.then((response) => response.text())
.then((data) => {
return data
})
}
</script>
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;
}
}
}
如何在 Blazor 服务器端获取 IP 地址和浏览器等客户端信息name/version?
请注意,这仅指服务器端 Blazor。
"There is no a good way to do this at the moment. We will look into how we can provide make this information available to the client."
解决方法
客户端向服务器发出 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;
};
后端(ASP.NET Core 3.0):
[HttpPost("[action]")]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public string GetIP()
{
return HttpContext.Connection.RemoteIpAddress?.ToString();
}
请注意,这并不安全,ip 号码可能会被欺骗,所以不要用于任何重要的事情。
好吧,我今天早上遇到了这个问题,我为服务器端 Blazor 解决它的方法是创建一个 class,然后您可以将其作为作用域服务注入 _host.cshtml ,然后在您的 Blazor 组件上的任何位置访问它,因为 Razor 页面已经支持它。
public class BlazorAppContext
{
/// <summary>
/// The IP for the current session
/// </summary>
public string CurrentUserIP { get; set; }
}
Startup.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>();
...
}
_host.cshtml:
@inject IHttpContextAccessor httpContextAccessor
@{
BlazorAppContext.CurrentUserIP = httpContextAccessor.HttpContext.Connection?.RemoteIpAddress.ToString();
}
您也可以尝试通过 DI 使用 Scoped 方法。
注解:
如文档中所述,“Blazor WebAssembly 应用目前没有 DI 范围的概念。范围注册服务的行为类似于单例服务。但是,Blazor 服务器托管模型支持范围生命周期。在 Blazor 服务器中应用程序,范围服务注册的范围是连接。因此,对于应该范围为当前用户的服务,最好使用范围服务,即使当前意图是 运行 中的客户端浏览器。"
希望对您有所帮助。
在 aspnetcore3.1 中,这对我有用:
- 制作特殊 class 以保存所需信息:
public class ConnectionInfo
{
public string RemoteIpAddress { get; set; } = "-none-";
}
- 在
_Host.cshtml
中创建实例并作为参数传递给App
组件:
@{
var connectionInfo = new ConnectionInfo()
{
RemoteIpAddress = Request.HttpContext.Connection.RemoteIpAddress.ToString()
};
}
...
<component type="typeof(App)"
render-mode="ServerPrerendered"
param-ConnectionInfo="connectionInfo" />
- 在
App.razor
中捕获并 re-publish 为CascadingValue
:
<CascadingValue Value="connectionInfo">
<Router AppAssembly="typeof(Program).Assembly">
...
</Router>
</CascadingValue>
@code {
[Parameter]
public ConnectionInfo? connectionInfo { get; set; }
}
- 在任何 child page/component 中获得
CascadingParameter
:
@code {
[CascadingParameter]
private ConnectionInfo? connectionInfo { get; set; }
}
这里唯一的问题是漫游用户 - 当用户更改他的 IP 地址并且 Blazor 没有“捕获”这个(例如后台的浏览器选项卡)时,您将拥有旧的 IP 地址,直到用户刷新 (F5) 页面。
以下是 2021 年在服务器端 Blazor for .NET 5 中的操作方法。
请注意,我的解决方案只会为您提供一个 IP 地址,但使用我的解决方案获取用户代理应该很容易。
我将只复制我的博客 post 的内容:https://bartecki.me/blog/Blazor-serverside-get-remote-ip
TLDR:
您可以使用 JavaScript 调用您自己公开的端点,该端点将 return 使用以下代码远程连接 IP:
RemoteIpAddress = Request.HttpContext.Connection.RemoteIpAddress.ToString()
...缺点是必须处理您的反向代理服务器(如果有的话),否则您只会获得反向代理的 IP 地址。
或者您可以使用 JavaScript 调用外部端点,这将为您 return 一个 IP 地址,但缺点是您必须配置 CORS,即使这样它也可能被某些广告拦截程序阻止扩展。
详情:
两种方法
方法一:使用JavaScript
调用外部服务优点:
- 如果你使用nginx、traefik等反向代理,会稍微简单一些
缺点:
- 可能被外部阻止extensions/adblockers
- 您将必须配置 CORS
_Host.cshtml
<script>
window.getIpAddress = () => {
return fetch('https://jsonip.com/')
.then((response) => response.json())
.then((data) => {
return data.ip
})
}
</script>
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;
}
}
}
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");
}
方法 2:在我们的 Blazor 应用程序中公开一个端点并使用 JavaScript
调用它优点:
- 您不必配置 CORS
- 不会被扩展程序或广告拦截器阻止
缺点:
- 如果您使用反向代理,如 nginx、traefik 等,可能会稍微复杂一些
现在要小心,因为您将使用这种方法,因为如果您使用反向代理,那么您实际上会收到反向代理 IP 地址。 很可能您的反向代理已经在以某种方式转发外部客户端的 IP 地址 header,但这取决于您自己想办法。
示例: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;
}
}
Startup.cs
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers(); //remember to map controllers if you don't have this line
endpoints.MapBlazorHub();
endpoints.MapFallbackToPage("/_Host");
});
_Host.cshtml
<script>
window.getIpAddress = () => {
return fetch('/api/info/ipaddress')
.then((response) => response.text())
.then((data) => {
return data
})
}
</script>
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;
}
}
}