2013-06-18 2 views
11

Название вопроса возобновляется в значительной степени: где я могу подтвердить авторизацию для команды?Где подтвердить авторизацию для команды?

Например, установка клиента как предпочтительный включает:

  • MarkAsPreferred действие контроллера (может быть Winforms или любой другой);
  • SetCustomerAsPreferredCommand;
  • SetCustomerAsPreferredCommandHandler;
  • Customer.MarkAsPreferred() (область);

я определил 3 места для проверки авторизации:

  • UI для отображения цели (пользователь не должен видеть ссылку/кнопку, если он/она не имеет доступа к нему);
  • Контрольное действие для проверки того, что пользователь имеет право называть эту команду; команды считаются всегда успешными (в отношении проверки, но я также принимаю авторизацию), и мы имеем возможность сообщить пользователю об отсутствии доступа;
  • внутри команды непосредственно перед вызовом логики домена;

SomeView.cshtml

if (authorizationService.Authorize("MarkCustomerAsPreferred)) 
{ 
    // show link 
} 

CustomerController

[HttpPost] 
public ActionResult MarkAsPreferred(Guid id) 
{ 
    if (!authorizationService.Authorize("MarkCustomerAsPreferred)) 
    { 
     return RedirectToAction("Unauthorized"); 
    } 

    var MarkCustomerAsPreferredCommand { Id = id }; 
    ... 
} 

MarkCustomerAsPreferredCommandHandler

public void Handle(MarkCustomerAsPreferredCommand command) 
{ 
    if (!authorizationService.Authorize("MarkCustomerAsPreferred")) 
    { 
     throw new Exception("..."); 
    } 

    customer.MarkAsPreferred(); 
} 

Мой вопрос: Do I нужен, чтобы подтвердить авторизацию в 3-х местах, или я просто переусердствую?

Я искал по всему Интернету, но не нашел ни одного примера или справки об этом.

Редактировать

После дополнительных исследований и некоторые тесты, я думаю, оберточной команду, чтобы добавить поведение (авторизация, проверка, протоколирование), как Деннис Тауба предложили проще и чище реализовать.

Я нашел this blog post, который объясняет именно эту концепцию.

О наличии нескольких обработчиков для одной команды, мне не нужно реализовывать один обработчик команд для каждого поведения для каждой исходной команды, одна команда обертки может обернуть все обработчики.

ответ

5

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

class AuthorizationHandler : IHandle<SetCustomerAsPreferred> { 

    IHandle<SetCustomerAsPreferred> innerHandler; 

    public AuthorizationHandler(IHandle<SetCustomerAsPreferred> handler) 
    { 
     innerHandler = handler; 
    } 

    public void Handle(SetCustomerAsPreferred command) 
    { 
     if (/* not authorized */) 
      throw ... 
     innerHandler.Handle(command); 
    } 

} 

class SetCustomerAsPreferredCommandHandler : IHandle<SetCustomerAsPreferred> { 

    public void Handle(SetCustomerAsPreferred command) 
    { 
     // do the work 
    } 

} 
+0

Обтекание команды - отличный способ добавить функциональность, но возникает несколько вопросов: 1) Это открывает множество возможностей, например, протоколирование и валидацию; поэтому для каждой команды я реализую обработчики команд N (фактический обработчик, ведение журнала, проверка, авторизация и т. д.)? 2) Теперь у меня есть два или более обработчика для одной и той же команды, как мой контейнер IoC правильно настроит их для ввода в контроллер? 3) Должен ли я до сих пор проверять авторизацию в контроллере перед тем, как выполнять команды, чтобы свести к минимуму риск их не принимать? –

+1

Этот подход немного вонючий с моей точки зрения, так как вы определили 2 обработчика для одной и той же команды. Я считаю, что проверка подлинности должна выполняться в момент выдачи команды. по крайней мере, с asp.net mvc У меня будет фильтр авторизации (который, вероятно, будет работать и с web api). Здесь речь идет о предпочтении. @LuizDamim По крайней мере, мой ServiceBus (который я недавно написал) имеет возможность игнорировать некоторые типы при автоматической настройке, и, вероятно, эта служебная шина использует этот параметр. – MikeSW

+0

@LuizDamim 1) Ведение журнала не должно выполняться как обработчик команд, я имею в виду, что любой обработчик сообщений может принимать зависящую от журнала информацию. Проверка выполняется в 2-х ладонях с различными целями: вы проверяете входные данные на уровне контроллера и проверки бизнес-правил, которые выполняются самим объектом домена. 3) С asp.net mvc я бы сказал, что пользователь не должен доходить до этого действия, если он не имеет права выдавать эту команду. – MikeSW

4

Это хороший пользовательский интерфейс, который имеет эту проверку в представлении, поэтому пользователь не будет щелкать по ошибке. Я считаю проверку контроллера «реальной», потому что там создается команда.Если у пользователя нет прав, она не должна создавать (или даже достигать этого действия) команду.

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

+1

Было бы целесообразно проверить авторизацию в обработчике команд, чтобы разрешить повторное использование домена другой службой. Например, предоставление API с использованием ASP.NET Web API. Вы можете создать декоратор обработчика команд, который вызывается перед каждым обработчиком команд, чтобы «автоматически» вызвать службу авторизации с помощью команды в качестве операции для проверки. –

+0

Я был в значительной степени настроен на проверку авторизации в пользовательском интерфейсе и контроллере, но, как предложил Деннис, команда обертывания, которая делает это до фактической обработки (и, если ее так просто реализовать, как кажется), дает еще один уровень проверки _ для free_. Повторное использование команд, как сказал @Ben Smith, является еще одним преимуществом, о котором я не думал. –

+0

@BenSmith На самом деле это не плохая идея для служебной шины для поддержки действий обработчика pre и post, аналогичных фильтрам asp.net mvc. – MikeSW