我有一个n层的web api 2项目,其结构如下:
Web控制器具有注入Autofac的相应服务,并且每个服务都注入了相应的存储库。这很好用。
现在,我需要为业务逻辑目的注入一个包含有关用户信息的对象。与此类似:
public class OrderService : IOrderService
{
private readonly IOrderRepo _Repo;
private readonly EnterpriseUser _EnterpriseUser;
public OrderService(IOrderRepo repo, EnterpriseUser enterpriseUser)
{
this._Repo = repo;
this._EnterpriseUser = enterpriseUser;
}
....
}
用户信息是需要的,例如,如果它们是某个特权级别,那么他们的订单可以放在队列中以供管理员审阅,或者他们可以获得折扣。
我的问题出现在身份验证过程中。 EnterpriseUser
需要当前IIdentity
的索赔。
builder.Register(ctx =>
{
// Identity extension to retrieve claim from User
var userLinkCode = ctx.Resolve<HttpContextBase>().User.Identity.GetUserLinkCode();
// Retrieves a header from the request
var partnerLinkCode = ctx.Resolve<ConnectionInfo>().PartnerLinkCode;
return EnterpriseUser.Create(userLinkCode, partnerLinkCode);
})
.As<EnterpriseUser>()
.InstancePerRequest();
因此,当用户的令牌过期时,Autofac将抛出以下异常
注册为创建“LVV.Services.EnterpriseUser”实例的委托返回null
因为声明是空的并且AuthorizeAttribute
永远不能拒绝401 Unauthorized
的调用,因为控制器的构造函数在AuthorizeAttribute
之前运行。
有没有已知的工作?
如果委托返回null,可能是用401
拒绝调用的方法?
或者是将更多有关用户信息注入服务层的更好方法,同时仍允许OAuth身份验证过程正常运行。
我建议在这里实现NullObject pattern让AuthorizeAttribute
完成它的工作,而不是将Autofac和contructors与原始空值混淆。我没有看到你的整个代码,所以下面的例子只是这个想法的一个例子。假设我们以这种方式扩展EnterpriseUser
:
public class EnterpriseUser
{
/// <summary>
/// Always true for real user
/// </summary>
public virtual bool IsAuthentificated => true;
public static EnterpriseUser Create(string userLinkCode, string partnerLinkCode)
{
if (string.IsNullOrEmpty(userLinkCode) ||
string.IsNullOrEmpty(partnerLinkCode))
{
return new DummyEnterpriseUser();
}
// create true user here with usin link codes
return new EnterpriseUser(userLinkCode, partnerLinkCode);
}
// Some usefull code here
}
/// <summary>
/// NullObject implementation for <see cref="EnterpriseUser"/>
/// </summary>
public class DummyEnterpriseUser : EnterpriseUser
{
/// <summary>
/// Always false for dummy user
/// </summary>
public override bool IsAuthentificated => false;
public DummyEnterpriseUser()
{
}
}
添加IsAuthentificated
标志以防万一,你可能不需要它。我还假设您的扩展方法GetUserLinkCode
在空索赔的情况下返回null
。最终的实现将取决于您的代码。