Autofac and the HttpContext



我有很多服务需要访问当前用户。 我设置了一个绑定到当前HttpContextPrincipalProvider,我还为每个请求注册了它,以便一旦实例化,它永远不会丢失上下文。 它看起来像这样:

public class PrincipalProvider : IPrincipalProvider
{
// Readonly fields
private readonly HttpContext _current;
/// <summary>
/// Default constructor
/// </summary>
public PrincipalProvider()
{
_current = HttpContext.Current;
}
/// <summary>
/// Gets the current user
/// </summary>
public IPrincipal User => _current?.User;
}

我把它装订成这样:

builder.RegisterType<PrincipalProvider>().As<IPrincipalProvider>().InstancePerRequest();

现在,任何注入此内容的服务都应该公开用户。我遇到的问题很简单。如果我有这样的控制器设置:

public OrdersController(IOrderProvider provider)
{
_provider = provider;
}

IOrderProviderIPrincipleProvider延迟注入其中,因此在这种情况下,用户可用,因为父服务是在控制器上创建的。问题是,如果它没有注入到服务中,而是用于注入到服务中的另一个服务。 例如,我有这个控制器:

public UsersController(IUserProvider provider, IAdvancedEncryptionStandardProvider encyptionProvider, IPhotoManager photoManager)
{
_userProvider = provider;
_encryptionProvider = encyptionProvider;
_photoManager = photoManager;
}

IUserProvider没有注入IPrincipalProvider,但它确实有另一个服务:

public TroposSessionRequest(CormarConfig config, IAdvancedEncryptionStandardProvider encryptionProvider, Lazy<IPrincipalProvider> principalProvider)
{
_config = config;
_encryptionProvider = encryptionProvider;
_principalProvider = principalProvider;
}

这里的问题是,当创建TroposSessionRequest时,HttpContext不可用,因此为空。 我希望有一种方法可以在上下文可用时实例化IPrincipleProvider,然后将其保留在整个请求中。 我们可以为每个请求执行此操作,因为几乎总是需要委托提供程序

有谁知道如何做到这一点?

解决此问题的最简单方法是简单地访问User访问器中的HttpContext.Current

public IPrincipal User => HttpContext.Current?.User;

如果你担心可测试性,你可以相对容易地模拟HttpContext.Current.User。

如果您打算使用 DI 解决它,则可以将HttpContext抽象为IHttpContextAccessor依赖项(但由于您仍然依赖于HttpContext类型,因此在测试方面您仍然处于同一条船上(。

public class PrincipalProvider : IPrincipalProvider
{
// Readonly fields
private readonly IHttpContextAccessor _httpContextAccessor;
/// <summary>
/// Default constructor
/// </summary>
public PrincipalProvider(IHttpContextAccessor httpContextAccessor)
{
_httpContextAccessor = httpContextAccessor;
}
/// <summary>
/// Gets the current user
/// </summary>
public IPrincipal User => _httpContextAccessor.HttpContext?.User;
}

相关内容

最新更新