无论如何都要访问当前主体并且在请求使用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
}
答案 0 :(得分:5)
您可以注册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>();
答案 1 :(得分:3)
这是否意味着它是不可能的,因为这一步是在创建控制器之前进行的?
绝对是你创造它的方式。我并不完全熟悉simple-injector,但我打赌使用Lazy<>
可能会有所帮助:
var request = container.GetCurrentHttpRequestMessage();
var principal = new Lazy<ClaimsPrincipal>(() =>
{
return request.GetRequestContext().Principal as ClaimsPrincipal;
});
未经过测试,但是当实际上需要主值(我假设某个时候以后,在同一个类中采用不同的方法)时,您可以使用principal.Value
并且然后会运行并检索您的ClaimsPrincipal
。这些是巨大的假设,因为没有代码可以看到一切都是如何连线的。如果您可以提供如何获取dbcontext的连接字符串(如何连接),我可以为您提供完整的解决方案。