简单注入器使用 OWIN 在 WebAPI 中获取当前主体
本文关键字:获取 主体 WebAPI 注入器 OWIN 简单 | 更新日期: 2023-09-27 18:32:46
是否可以使用Simple Injector在请求到达控制器之前访问当前主体?我正在使用 OWIN 和 Asp.net 身份。
我有一个注入到控制器中的 DbContext,但此上下文将根据经过身份验证的用户获取其连接字符串。这就是我目前所拥有的,
container.RegisterWebApiRequest<TenantDbContext>();
container.RegisterWebApiRequest<ITenantConnectionStringProvider>(() => new TenantConnectionStringProvider(container));
然后在我的 TenantConnectionStringProvider 中,我有这个,
var request = container.GetCurrentHttpRequestMessage();
var principal = request.GetRequestContext().Principal as ClaimsPrincipal;
但校长没有索赔。我意识到这些声明仅在创建控制器后可用。这是否意味着这是不可能的,因为此步骤是在创建控制器之前完成的?
编辑:这基本上是代码其余部分的作用:
WebAPI 控制器
public CampaignsController(TenantDbContext context, ILog log)
{
this.campaignService = campaignService;
this.log = log;
}
租户上下文(仅从 EF 的 DbContext 继承(:
public TenantDbContext(ITenantConnectionStringProvider provider)
: base(provider.GetConnectionString())
{
}
在搞砸了一会儿之后,我能够做到这一点,但感觉很笨拙。我添加了一个在身份验证后发生的 OWIN 中间件。我不确定为什么,但我这里有所有经过身份验证的用户信息,但是当它转到 TenantConnectionStringProvider 时,这些信息在 HttpRequestMessage 上都不可用。
app.Use(async (context, next) =>
{
using (container.BeginExecutionContextScope())
{
CallContext.LogicalSetData("Claims", context.Authentication.User.Claims);
var request = (OwinRequest)context.Request;
await next();
}
});
然后在我的 TenantConnectionStringProvider 中,我只是做了这个,
public string GetConnectionString()
{
var context = (IEnumerable<Claim>)CallContext.LogicalGetData("Claims");
return "test";//get claim from context to get the connection string
}
您可以注册一个Func<ClaimsPrincipal>
(工厂(并将其注入到您的TenantConnectionStringProvider
类中:
public class TenantConnectionStringProvider : ITenantConnectionStringProvider
{
private readonly Func<ClaimsPrincipal> _claimsPrincipalFactory;
public TenantConnectionStringProvider(Func<ClaimsPrincipal> claimsPrincipalFactory)
{
_claimsPrincipalFactory = claimsPrincipalFactory;
}
public void TestMethod()
{
// Access the current principal
var principal = _claimsPrincipalFactory();
}
}
注册应如下所示(不确定...
// Register your types, for instance using the scoped lifestyle:
container.RegisterSingleton<Func<ClaimsPrincipal>>(() =>
{
// Not sure of which one to use.
//return (ClaimsPrincipal)HttpContext.Current.User;
//return (ClaimsPrincipal)Thread.CurrentPrincipal;
return (ClaimsPrincipal)Context.User;
});
container.RegisterWebApiRequest<ITenantConnectionStringProvider, TenantConnectionStringProvider>();
这是否意味着这是不可能的,因为此步骤是在创建控制器之前完成的?
绝对是你创造它的方式。 我不完全熟悉简单的注射器,但我敢打赌使用Lazy<>
可能会有所帮助:
var request = container.GetCurrentHttpRequestMessage();
var principal = new Lazy<ClaimsPrincipal>(() =>
{
return request.GetRequestContext().Principal as ClaimsPrincipal;
});
未经测试,但是当您实际需要主体值时(我假设稍后,在同一类中的不同方法中(,您可以使用principal.Value
然后它会运行并检索您的ClaimsPrincipal
。 当然,这些都是巨大的假设,因为没有代码来查看所有内容是如何连接的。 如果您可以提供如何获取数据库上下文的连接字符串(如何连接(,我可能会为您提供一个完整的解决方案。