Web API 2 中使用依赖关系注入的服务授权



我有一个 n 层 Web api 2 项目,其结构如下:

  1. 网页图层
  2. 服务/业务层
  3. 数据/存储库层

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 模式,让AuthorizeAttribute完成它的工作,而不是将 Autofac 和构造器与原始空值混淆。我没有看到你的整个代码,所以下面的例子只是这个想法的例证。假设我们以这种方式扩展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。当然,最终的实现将取决于您的代码。

最新更新