【问题标题】:When is ActionController.HttpContext set?ActionController.HttpContext 什么时候设置?
【发布时间】:2022-02-21 15:21:35
【问题描述】:

我正在尝试实现一个类似于 Jason Taylor 的 CleanArchitecture 设计的 ASP.NET Core MVC Web 应用程序。在 WebUi “层”中,我尝试实现 IIdentityService 的抽象,我想在其中访问与当前 HttpRequest 关联的 ClaimsPrincipal

在github上翻了一番源码后,发现Controller.User属性来源于ControllerBase.HttpContext?派生自ControllerContext,后者又派生自ActionContext,其中HttpContext属性定义为

/// <summary>
/// Gets or sets the <see cref="Http.HttpContext"/> for the current request.
/// </summary>
/// <remarks>
/// The property setter is provided for unit test purposes only.
/// </remarks>
public HttpContext HttpContext
{
    get; set;
}

在这里,我遇到了死胡同。我假设该属性是由一些中间件初始化的(即 Microsoft.Identity 的 .AddAuthentication() / .AddAuthorization()),但我想确认一下,所以我知道如何在我的服务中获取对该对象的引用。

IPrincipals 的其他来源,我从中找到了ClaimsPrincipal

System.Web.HttpContext.Current.User
ClaimsPrincipal.Current
Thread.CurrentPrincipal

IHttpContextAccessor _httpContextAccessor;
var principal = _httpContextAccessor.HttpContext?.User;

IHttpContextAccessor here 的文档,但我不知道Controller.User 指向的是哪个。

【问题讨论】:

  • 你的“服务”是单身吗?然后你有一个挑战...... HttpContext 设置每个请求。您可以按照here 的描述从您的控制器(也创建每个请求)访问它
  • @JHBonarius Is 被限定并注入核心,在命令 (CQRS) 中使用它来创建/删除/...主体和/或注入用于查询主体的控制器是否Principal.Identity.IsAuthenticated
  • 如果你将作用域服务注入到控制器中,它将与控制器具有相同的作用域,因此具有相同的 IHttpContextAccessor。全部按请求。

标签: asp.net-core asp.net-core-mvc asp.net-core-identity


【解决方案1】:

在 @JHBonarius 在 cmets 中提示正确方向后,我在 the official documentation 中找到了一个记录在案的案例

使用自定义组件中的 HttpContext

对于其他需要访问的框架和自定义组件 HttpContext,推荐的做法是注册一个依赖 使用内置的依赖注入 (DI) 容器。 DI 容器将 IHttpContextAccessor 提供给任何类 在其构造函数中将其声明为依赖项:

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddControllersWithViews();
builder.Services.AddHttpContextAccessor();
builder.Services.AddTransient<IUserRepository, UserRepository>();
在以下示例中:

UserRepository 声明它对 IHttpContextAccessor 的依赖。这 依赖关系在 DI 解析依赖链时提供,并且 创建一个 UserRepository 的实例。

public class UserRepository : IUserRepository {
    private readonly IHttpContextAccessor _httpContextAccessor;

    public UserRepository(IHttpContextAccessor httpContextAccessor) =>
        _httpContextAccessor = httpContextAccessor;

    public void LogCurrentUser()
    {
        var username = _httpContextAccessor.HttpContext.User.Identity.Name;

        // ...
    } 
} 

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-07-28
    • 1970-01-01
    • 2011-05-15
    • 2020-03-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-02-15
    相关资源
    最近更新 更多