如何在服务器端 Blazor 中使用 HttpContext 对象来检索有关用户、用户代理的信息

Posted

技术标签:

【中文标题】如何在服务器端 Blazor 中使用 HttpContext 对象来检索有关用户、用户代理的信息【英文标题】:How to use the HttpContext object in server-side Blazor to retrieve information about the user, user agent 【发布时间】:2020-04-19 15:23:50 【问题描述】:

IP 地址等。很多时候,当用户询问如何在 Server Blazor 应用程序中执行此操作时,他们要么被告知这是不可能的,要么有时提供了采用 JSInterop 的部分解决方案。但是可以在不诉诸 JSInterop 的情况下完成吗?这是答案...

【问题讨论】:

【参考方案1】:

HttpContext 对象不能与 Blazor Server 应用程序一起使用的虚构已经在 *** 上传播了很长时间,现在是时候取消它了。

当 WebSocket 连接运行时,HttpContext 确实不可用,但必须清楚:当您键入 url 并按 enter 按钮时,与服务器端 Blazor 应用程序的连接是HTTP 连接,而不是 WebSocket 连接。

因此,您的应用可以访问和使用HttpContext,就像在 Razor Pages 应用或 MVC 应用中使用它一样,包括获取用户代理和 IP 地址。以下代码示例演示了如何使用HttpContext 本地获取用户代理和IP 地址,而不使用应作为最后手段使用的JSInterop,并将提取的值传递给App 组件。

    将文件添加到Pages 文件夹并将其命名为_Host.cshtml.cs。 将此代码添加到文件中:
public class HostModel: PageModel

    private readonly IHttpContextAccessor _httpContextAccssor;
    
    public HttpContextFeatureModel(IHttpContextAccessor httpContextAccssor)
    
        _httpContextAccssor = httpContextAccssor;    
    

    public string UserAgent  get; set; 
    public string IPAddress  get; set; 
    
    // The following links may be useful for getting the IP Adress:
    // https://***.com/questions/35441521/remoteipaddress-is-always-null
    // https://***.com/questions/28664686/how-do-i-get-client-ip-address-in-asp-net-core
    
    public void OnGet()
    
        UserAgent = _httpContextAccssor.HttpContext.Request.Headers["User-Agent"];
        // Note that the RemoteIpAddress property returns an IPAdrress object 
        // which you can query to get required information. Here, however, we pass 
        // its string representation
        IPAddress = _httpContextAccssor.HttpContext.Connection.RemoteIpAddress.ToString();  
    

您可能需要以下一种或多种用法:

using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Text.Encodings.Web;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Identity.UI.Services;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.Extensions.Logging;
using Microsoft.AspNetCore.Http;
    将以下行添加到您的 Host.cshthml 页面(在页面顶部靠近使用和其他内容的地方):
@model HostModel
    App 组件中,定义两个参数属性,它们将获取并存储从位于_Host.cshtml 的组件标签中传递给它的用户代理和IP 地址。

App.razor:

<p>UserAgent: @UserAgent</p>
<p>IPAddress: @IPAddress</p>

@code

    [Parameter]
    public string UserAgent  get; set; 

    [Parameter]
    public string IPAddress  get; set; 

    _Host.cshtml中像这样更新组件标签(这个方法现在已经过时了):
<app>
    <component type="typeof(App)" render-mode="ServerPrerendered" param-UserAgent="@Model.UserAgent" param-IPAddress="@Model.IPAddress" />
</app>

在当前的 Blazor 服务器端应用程序中,可以这样完成:

<div>
    @(await Html.RenderComponentAsync<App>(RenderMode.Server, new  IPAddress = Model.IPAddress, UserAgent = Model.UserAgent ))
</div>
    services.AddHttpContextAccessor(); 添加到StartupConfigureServices 方法以启用对HttpContext 的访问。

就是这样。您也可以将 Identity UI 添加到您的 Blazor 服务器应用程序中,并在用户通过身份验证后应用上面显示的相同过程从 HttpContext 中提取声明主体(这样做仅用于学习目的,因为您应该使用AuthenticationStateProvider)。

Here's also a link关于当前主题的官方文档。

【讨论】:

如果没有 HttpContextAccessor 我本可以做到的:github.com/aspnet/AspNetCore/issues/… 是否有 .net core 版本可以让您的指令编译? 所以我想我一定在这里遗漏了一些东西。您上面推荐的代码似乎确实可以工作并获得所需的内容,但是您如何从 Blazor SSA 中的其他 razor 组件或服务访问 _Host.cshtml.cs 中的这些新属性? 您可以将它们保存在本地存储中,组件和服务可以从中读取它们。 参见我上面的第一条评论,我说不需要 HttpContextAccessor,因为您可以直接访问作为 ModelPage 对象的属性提供的 HttpContext【参考方案2】:

在您的启动 > ConfigureServices 中:

 services.AddControllers();

在您的启动中 > 配置:

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

添加一个文件夹名称:Controllers

添加一个控制器名称:InitController

添加这样的方法:

   [Route("[controller]/[action]")]
    public class InitController : Controller
    
    public IActionResult UserInfo(string redirectUri)
        
           var request = Request.HttpContext;


            return LocalRedirect(redirectUri);
        

在请求变量中,所有数据都存在

最后为了从页面或组件重定向用户使用此代码:

@inject NavigationManager NavigationManager

@code
     protected override Task OnInitializedAsync ()
               var uri = new Uri(NavigationManager.Uri)
            .GetComponents(UriComponents.PathAndQuery, UriFormat.Unescaped);

           var query = $"?redirectUri=Uri.EscapeDataString(uri)";
          NavigationManager.NavigateTo("/Init/UserInfo" + query, forceLoad: true);
           StateHasChanged();

            return base.OnInitializedAsync();


        

【讨论】:

通过重定向来获取用户代理似乎不直观... 在本例中,我无法查看 HttpContext 数据的位置。 在花了一天时间试图让批准的解决方案发挥作用后,我明白为什么会建议这样做。请参阅我上面的评论。

以上是关于如何在服务器端 Blazor 中使用 HttpContext 对象来检索有关用户、用户代理的信息的主要内容,如果未能解决你的问题,请参考以下文章

如何在服务器端 Blazor 中访问 HttpContext?

如何在服务器端 Blazor 组件中访问实体框架 DbContext 实体

如何在Blazor服务器端处理窗口或主体滚动?

如何在服务器端 Blazor 中使用 HttpContext 对象来检索有关用户、用户代理的信息

如何在服务器端 Blazor 中存储会话数据

如何从 Blazor 服务器端应用程序中的 Razor 页面导航到 Blazor 组件?