Web API 2中具有依赖注入的服务授权

时间:2018-09-10 20:29:07

标签: c# .net asp.net-web-api2 autofac

我有一个结构如下的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之前运行。

是否有已知的解决方法?

如果委托返回空值,是否可以用401拒绝呼叫?

或者是将有关用户的信息注入服务层的更好方法,同时仍然允许OAuth身份验证过程正常运行。

1 个答案:

答案 0 :(得分:2)

我建议在此处实现NullObject pattern,以使AuthorizeAttribute发挥作用,不要将Autofac和构造函数与原始null值混淆。我看不到您的完整代码,因此下面的示例仅是该想法的说明。假设我们以这种方式扩展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。当然,最终的实现将取决于您的代码。

相关问题