Как мне настроить Ambient Context DI в Unity в MVC3? - PullRequest
2 голосов
/ 11 января 2012

В настоящее время я использую Unity с Unity.Mvc3 в своем приложении MVC3, которое использует проверку подлинности Windows.Я также читаю о внедрении зависимостей и пытаюсь настроить Ambient Context для некоторой проверки авторизации.

У меня есть абстрактный класс AuthorizeContext со статическим свойством Current, который содержит одну из трех реализаций этого класса:

  1. AuthorizeRoleContext, используемый для производства, который принимает строку и IPrincipal посредством инжекции в конструктор и является всего лишь уровнем косвенности для вызова IPrincipal.IsUserInRole всякий раз, когда выполняется запрос или запрос на авторизацию,Введенная строка используется в качестве префикса домена для роли.

  2. AuthorizeContextAllowAll, используется для разработки и иногда тестирования, который всегда разрешает все запросы и требования для авторизации, используя конструктор по умолчанию.

  3. AuthorizeContextAllowNothing, используется для тестирования минимально допустимой функциональности, которая всегда отклоняет все запросы на авторизацию.

  4. В будущем добавьте еще один и проверьте авторизациючерез базу данных ...?

Так что я могу вручную соединить вещи, выполнив (например, в Application_BeginRequest):

AuthorizeContext.Current = новый AuthorizeRoleContext (HttpContext.Current.User));

и затем вызовите

AuthorizeContext.Current.Demand ("someRole");

Это прекрасно работает, но я 'я ищу правильный путь (и место) для соединения с Unity, избегая при этом антишаблонов Service Locator.Поэтому мой вопрос: как мне это сделать?

Некоторые проблемы, с которыми я сталкиваюсь при регистрации Unity:

  • У меня нет HttpContext.Current.User на Application_Startпоэтому я не могу внедрить его в AuthorizeRoleContext в то время
  • Я не знаю, как назначить реализацию статическому свойству AuthorizeContext.Current

Теперь, может быть, я должен просто сделать [Authorize(Roles = "Role1")] везде и просто позволяйте MVC3 делать свое дело, но:

  • Я также использую его для создания своего меню и, возможно, хочу использовать его в других местах для проверки авторизации.
  • Я бы хотел поменять проверку авторизации с другими реализациями (например, разрешить все), чтобы мне не приходилось назначать Группы Windows каждому разработчику / тестеру.
  • Мне кажется, чтоиспользуйте префикс домена для роли с IPrincipal.IsUserInRole, иначе он не будет работать в dev / test / production.Конечно, производство осуществляется в среде клиентов, использующих совершенно разные доменные имена.По этой причине я сделал доменное имя настраиваемым и внедрил его.
  • Я бы хотел провести модульное тестирование.

Но, возможно, я все еще на неверном пути с этими я работаю над проблемами, которых там нет.:)

1 Ответ

4 голосов
/ 12 января 2012

Я не уверен, что этот дополнительный уровень косвенности добавляет какую-либо ценность.IPrincipal уже является полиморфным типом, поэтому вы можете выполнить именно то, что вам нужно, гораздо более простым способом.

Вместо AuthorizeRoleContext вы можете просто использовать IPrincipal, предоставляемый Windows Authentication (WindowsPrincipal).

Вместо AuthorizeContextAllowAll вы можете просто реализовать IPrincipal следующим образом:

public AllowAllPrincipal : IPrincipal
{
    public bool IsInRole(string role)
    {
        return true;
    }

    // also implement the Identity property...
}

Вместо AuthorizeContextAllowNothing реализовать IPrincipal следующим образом:

public AllowNothingPrincipal : IPrincipal
{
    public bool IsInRole(string role)
    {
        return false;
    }

    // also implement the Identity property...
}

Чтобы настроить его, вы можете добавить его в Global.asax.cs:

private void OnAuthenticateRequest(object sender, EventArgs e)
{
    this.Context.User = this.container.Resolve<IPrincipal>();
}

Чтобы настроить Unity с «настоящим» IPrincipal, вы можете настроить его следующим образом:

this.container.RegisterType<IPrincipal>(
    new InjectionFactory(
        _ => HttpContext.Current.User));

Настроить Unity с AllowAllPrincipal намного проще:

this.container.RegisterType<IPrincipal, AllowAllPrincipal>();

, а также с AllowNothingPrincipal:

this.container.RegisterType<IPrincipal, AllowNothingPrincipal>();

Если вы должны настаивать на подключении собственного AuthorizeContext, вы можете сделать это аналогичным образом.

...