Pytanie Gdzie zweryfikować autoryzację dla polecenia?


Tytuł pytania zaczyna się od nowa: gdzie mogę zweryfikować autoryzację dla polecenia?

Na przykład ustawienie klienta jako preferowanego obejmuje:

  • MarkAsPreferred działanie kontrolera (może to być WinForm lub cokolwiek innego);
  • SetCustomerAsPreferredCommand;
  • SetCustomerAsPreferredCommandHandler;
  • Customer.MarkAsPreferred() (domena);

Zidentyfikowałem 3 miejsca, w których należy sprawdzić autoryzację:

  • Interfejs użytkownika do celów wyświetlania (użytkownik nie powinien widzieć linku / przycisku, jeśli nie ma do niego dostępu);
  • działanie kontrolera aby zweryfikować, czy użytkownik jest uprawniony do wywoływania tego polecenia; Polecenia są zawsze pomyślne (dotyczy sprawdzania poprawności, ale ja też zakładam autoryzację) i mamy szansę poinformować użytkownika o braku dostępu;
  • wewnątrz polecenia tuż przed wywołaniem logiki domeny;

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();
}

Moje pytanie brzmi: Czy ja potrzeba zweryfikować autoryzację w 3 miejscach lub jestem po prostu nadgorliwy?

Przeszukałem cały Internet, ale nie znalazłem żadnego przykładu ani odniesienia do tego.

Edytować

Po dalszych badaniach i niektórych testach myślę, że zawijanie poleceń dodawania zachowania (autoryzacja, sprawdzanie poprawności, rejestrowanie), jak sugerował Dennis Taub, jest łatwiejsze i bardziej przejrzyste w implementacji.

znalazłem ten wpis na blogu co dokładnie wyjaśnia tę koncepcję.

O posiadaniu wielu procedur obsługi dla jednego polecenia, nie muszę implementować jednej procedury obsługi dla każdego zachowania dla każdego oryginalnego polecenia, a jedno polecenie owijania może owijać wszystkie procedury obsługi.


11
2018-06-18 02:47


pochodzenie




Odpowiedzi:


Myślę, że ostateczna autoryzacja powinna zostać wykonana na poziomie usługi aplikacji, tj. W ramach obsługi polecenia. Można na przykład owinąć program obsługi komend za pomocą procedury autoryzacji.

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
    }

}

5
2018-06-18 15:10



Zawijanie polecenia jest dobrym sposobem na dodanie funkcjonalności, ale rodzi kilka pytań: 1) Otwiera to wiele możliwości, na przykład rejestrowanie i sprawdzanie poprawności; więc dla każdego polecenia zaimplementuję narzędzia obsługi komend N (rzeczywisty moduł obsługi, rejestrowanie, sprawdzanie poprawności, autoryzacja itd.)? 2) Teraz mam dwie lub więcej procedur obsługi dla tego samego polecenia, w jaki sposób mój kontener IoC skonfiguruje je poprawnie, aby wprowadzić je do kontrolera? 3) Czy nadal powinienem sprawdzać autoryzację w sterowniku przed obsługą poleceń, aby zminimalizować ryzyko, że nie zostaną one zaakceptowane? - Luiz Damim
To podejście jest nieco śmierdzące z mojego punktu widzenia, ponieważ zdefiniowałeś 2 procedury obsługi dla tego samego polecenia. Uważam, że sprawdzanie auth powinno być wykonywane w momencie wydania komendy. przynajmniej z asp.net mvc miałbym filtr autoryzacji (który prawdopodobnie działałby również z interfejsem sieciowym). Jest to kwestia preferencji. @LuizDamim Przynajmniej mój ServiceBus (który ostatnio napisałem) ma opcję ignorowania niektórych typów podczas wykonywania automatycznej konfiguracji i prawdopodobnie używana magistrala usług również ma tę opcję. - MikeSW
@LuizDamim 1) Rejestrowanie nie powinno być wykonywane jako obsługa komend, to znaczy każda procedura obsługi wiadomości może pobrać zależność od rejestratora. Sprawdzanie poprawności odbywa się w 2 partiach o różnych celach: sprawdzanie poprawności danych wejściowych odbywa się na poziomie kontrolera i sprawdzania reguł biznesowych, które wykonuje sam obiekt domeny. 3) Z ASP.NET mvc powiedziałbym, że użytkownik nie powinien osiągnąć tego działania, jeśli nie ma prawa do wydania tego polecenia. - MikeSW
@MikeSW Nie jestem pewien, czy rozumiem twoją troskę. Nawet podczas łączenia łańcuchów, z zewnętrznego punktu widzenia, wciąż istnieje tylko jeden pojedynczy handler na polecenie. Interfejs API jest ujednolicony, w zasadzie sprowadza się do typu podejścia opartego na rurach i filtrach. - Dennis Traub
Nie współpracuję bezpośrednio z łańcuchami. Polecenie chain -> handler -> command / event -> handler. Dla danego polecenia zawsze jest tylko 1 handler. IMO to przewodnik odpowiedzialny za zarządzanie bezpośrednio jednym konkretnym kontekstem. Twoje podejście działa, ale IMO jest mylące. Przecież prawdziwy handler nie jest Auth. Zdarza się, że używasz programu do obsługi funkcji filtra (który tak naprawdę nie obsługuje polecenia). - MikeSW


To dobry interfejs do weryfikacji w widoku, więc użytkownik nie kliknie go przez pomyłkę. Uważam, że kontroler sprawdza "prawdziwą", ponieważ tam jest miejsce, w którym polecenie jest tworzone. Jeśli użytkownik nie ma praw, nie powinien mieć możliwości utworzenia (lub nawet wykonania tej czynności) polecenia.

Myślę, że umieszczenie czeku w treserze jest trochę obleśne, ponieważ nie jest odpowiedzialnością za autoryzację i nie jest tak, że osoba obsługująca może być osiągnięta przez użytkownika bezpośrednio.


4
2018-06-18 06:12



Warto mieć kontrolę autoryzacji w procedurze obsługi komend, aby umożliwić ponowne użycie domeny z inną usługą. Przykład: udostępnianie interfejsu API przy użyciu interfejsu ASP.NET Web API. Można utworzyć dekorator obsługi komend, który jest wywoływany przed każdym programem obsługi komend, aby "automagicznie" wywoływać usługę autoryzacji za pomocą komendy jako operacji do sprawdzenia. - Ben Smith
Byłem prawie nastawiony na sprawdzanie autoryzacji na interfejsie użytkownika i kontrolera, ale jak sugerował Dennis, polecenie owijania, które robi to przed faktyczną obsługą (i jeśli jest tak łatwe do wdrożenia, jak się wydaje) daje kolejną warstwę weryfikacji za darmo. Ponowne użycie komend, jak powiedział @Ben Smith, to kolejna korzyść, o której nie myślałem. - Luiz Damim
@BenSmith Właściwie nie jest to zły pomysł, aby magistrala usług obsługiwała akcje poprzedzające i po komendach obsługi, podobne do filtrów mvc asp.net. - MikeSW