【问题标题】:Service Authorization with Dependency Injection in Web API 2Web API 2 中的依赖注入服务授权
【发布时间】:2018-09-10 20:29:06
【问题描述】:

我有一个 n-tiered web api 2 项目,其结构如下:

  1. Web 层
  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();

所以当用户的token过期时,Autofac会抛出如下异常

注册以创建“LVV.Services.EnterpriseUser”实例的委托返回 null

因为声明是空的,并且AuthorizeAttribute 永远无法拒绝使用401 Unauthorized 的调用,因为控制器的构造函数在AuthorizeAttribute 之前运行。

是否有已知的解决方法?

如果代理返回 null,是否可以通过 401 拒绝呼叫?

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

【问题讨论】:

  • 能否提供EnterpriseUserregistraction的代码?
  • @KozhevnikovDmitry 我已经添加了注册。

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


【解决方案1】:

我建议在这里实现NullObject pattern 以让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。最终的实现当然取决于你的代码。

【讨论】:

  • 哇,好简洁大方!
  • 乐于助人=)
猜你喜欢
  • 1970-01-01
  • 2018-03-24
  • 2018-10-19
  • 2020-03-23
  • 2019-02-25
  • 2019-04-05
  • 2013-12-04
  • 2018-12-31
  • 1970-01-01
相关资源
最近更新 更多