c# - Web API 2 中依赖注入(inject)的服务授权

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

我有一个结构如下的 n 层 web api 2 项目:

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

Web Controller 通过 Autofac 注入(inject)了相应的服务,并且每个服务都注入(inject)了相应的存储库。这很好用。

现在,出于业务逻辑目的,我需要注入(inject)一个对象,该对象包含有关用户的一些信息。类似这样:

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会抛出如下异常

A delegate registered to create instances of 'LVV.Services.EnterpriseUser' returned null

因为声明为空并且 AuthorizeAttribute 永远无法拒绝带有 401 Unauthorized 的调用,因为 Controller 的构造函数在 AuthorizeAttribute 之前运行.

是否有已知的解决方法?

如果委托(delegate)返回 null,是否有一种方法可以拒绝使用 401 的调用?

或者是一种更好的方式,可以将有关用户的信息注入(inject)服务层,同时仍允许 OAuth 身份验证过程发挥作用。

最佳答案

我建议实现 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。当然,最终实现将取决于您的代码。

关于c# - Web API 2 中依赖注入(inject)的服务授权,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52265034/

相关文章:

c# - 如何在(linq 和 lambda)中使用 select with max,min 函数?

c# - 仅当项目中存在属性时才在 aspx 中使用 Eval - 抛出 DataBinding 异常

c# - C# (.NET 2.0) 中 Windows 的进程间通信

c# - Page_Load 与 OnLoad

java - .NET 中 Guava 服务的替代方案?

asp.net-web-api - WebAPI 2.2 上的 Elmah.axd - 未找到 HTTP 资源

c# - Web Api 2 DatetimeOffset XML 序列化问题

c# - 注册事件时执行操作?

c# - 如何在 C# 2012 版中正确清理 Excel 互操作对象

.net - 您的项目未引用 ".NETFramework,Version=v4.5"框架。