Авторизация сервисов с внедрением зависимостей в Web API 2 - PullRequest
0 голосов
/ 10 сентября 2018

У меня есть n-уровневый проект web api 2, который структурирован так:

  1. Веб-слой
  2. Сервис / Бизнес Уровень
  3. Уровень данных / репозитория

Веб-контроллеры имеют соответствующую службу, внедренную с помощью 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 голосов
/ 11 сентября 2018

Я предлагаю реализовать шаблон 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 в случае пустых утверждений.Окончательная реализация будет зависеть от вашего кода.

...