Implementazione di DDD: utenti e autorizzazioni


16

Sto lavorando a una piccola applicazione cercando di comprendere i principi della progettazione guidata dal dominio. In caso di successo, questo potrebbe essere un pilota per un progetto più ampio. Sto cercando di seguire il libro "Implementing Domain-Driven Design" (di Vaughn Vernon) e sto cercando di implementare un forum di discussione simile e semplice. Ho anche controllato i campioni IDDD su github. Ho delle difficoltà ad adottare l'identità e l'accesso al mio caso. Vorrei fornire alcune informazioni di base:

  • Comprendo (si spera) il ragionamento alla base della separazione degli utenti e della logica dei permessi: è un dominio di supporto ed è un contesto limitato diverso.
  • Nel dominio principale, non ci sono utenti, solo autori, moderatori, ecc. Questi vengono creati raggiungendo il contesto di identità e accesso utilizzando un servizio e quindi traducendo gli oggetti utente ricevuti in e moderatore.
  • Le operazioni di dominio vengono chiamate con un ruolo correlato come parametro: ad es .:

    ModeratePost( ..., moderator);

  • Il metodo dell'oggetto dominio controlla se l'istanza del moderatore fornita non è nulla (l'istanza del moderatore sarà nulla se l'utente richiesto dal contesto Identità e accesso non ha il ruolo di moderatore).

  • In un caso, effettua un controllo aggiuntivo prima di modificare un Post:

    if (forum.IsModeratedby(moderator))

Le mie domande sono:

  • In quest'ultimo caso, i problemi di sicurezza non vengono nuovamente integrati nel dominio principale? In precedenza il libro indica "con chi può pubblicare un argomento o a quali condizioni è consentito. Un forum deve solo sapere che un autore lo sta facendo proprio ora".

  • L'implementazione basata sul ruolo nel libro è abbastanza semplice: quando un Moderatore è il dominio principale cerca di convertire l'ID utente corrente in un'istanza del Moderatore o in un Autore quando ne ha bisogno. Il servizio risponderà con l'istanza appropriata o null se l'utente non ha il ruolo richiesto. Tuttavia, non riesco a vedere come potrei adattarlo a un modello di sicurezza più complesso; il nostro attuale progetto per cui sto pilotando ha un modello piuttosto complesso con gruppi, ACL, ecc.

Anche con regole non molto complesse, come ad esempio: "Un post dovrebbe essere modificato solo dal suo proprietario o da un editore", questo approccio sembra fallire, o almeno non vedo il modo corretto di implementarlo.

Chiedere al contesto Identity and Access un'istanza di OwnerOrEditor non sembra corretto e finirei con un numero sempre maggiore di classi relative alla sicurezza nel dominio principale. Inoltre, dovrei passare non solo l'ID utente, ma l'identificatore della risorsa protetta (l'id del post, il forum, ecc.) Al contesto di sicurezza, che probabilmente non dovrebbe interessare a queste cose (è corretto? )

Estraendo i permessi dal dominio principale e controllandoli nei metodi degli oggetti del dominio o nei servizi, finirò al punto di partenza: mescolare i problemi di sicurezza con il dominio.

Ho letto da qualche parte (e tendo a concordare con esso) che queste cose relative alle autorizzazioni non dovrebbero far parte del dominio principale, a meno che la sicurezza e le autorizzazioni non siano il dominio stesso stesso. Una semplice regola come quella sopra giustificata rende la sicurezza parte del dominio principale?


Forse puoi trovare ciò di cui hai bisogno qui: stackoverflow.com/a/23485141/329660 Inoltre, solo perché il contesto di Controllo accesso conosce un ID risorsa non significa che abbia conoscenza del dominio su che tipo di entità è quella risorsa o che cosa è lo fa.
guillaume31,

Grazie, ho visto quel post in precedenza, il mio problema è esattamente quello che dice la modifica alla fine: mi piacerebbe spostare il controllo degli accessi dal mio dominio principale, ma sento di aver colpito un muro con la mia implementazione. Tuttavia, il tuo suggerimento sull'ID risorsa ha senso: poiché non uso il concetto di Utente o Ruolo nel dominio principale ma ruoli concreti, forse potrei usare il concetto di Risorsa nel BC della sicurezza e mapparli al relativo calcestruzzo concetto di dominio. Vale la pena provare, grazie!
LittlePilgrim

Gli esempi di codice nel link non rispondono almeno a "Non riesco a vedere come posso adattare questo a un modello di sicurezza più complesso" ?
guillaume31,

Il mio problema non è con l'implementazione del modello di sicurezza stesso, non riesco a vedere come dovrei mappare queste regole più complicate nel dominio. Come dovrebbe cambiare l'utente -> Mappatura dell'autore se non si tratta di un semplice modello basato sul ruolo dal punto di vista della sicurezza? Passare gli ID delle risorse all'altro contesto potrebbe funzionare, come HasPermissionToEdit(userId, resourceId)ma non mi sento giusto contaminare la logica del dominio con queste chiamate. Probabilmente dovrei controllare questi nei metodi di servizio dell'applicazione, prima di invocare la logica del dominio?
LittlePilgrim

Ovviamente dovrebbe essere nei servizi applicativi ... Ho pensato che fosse chiaro da parti del codice come UserService @AccessControlList[inf3rno]nella risposta a cui mi sono collegato.
guillaume31,

Risposte:


6

A volte è difficile distinguere tra regole di controllo reale degli accessi e invarianti di domini che rasentano il controllo degli accessi.

In particolare, le regole che dipendono dai dati disponibili solo nel corso di una particolare logica del dominio potrebbero non essere facilmente estraibili dal dominio. Di solito, il controllo di accesso viene chiamato prima o dopo l'esecuzione di un'operazione di dominio ma non durante.

L' assert (forum.IsModeratedBy(moderator))esempio di Vaughn Vernon probabilmente avrebbe dovuto essere al di fuori del Dominio, ma non è sempre fattibile.

Avrei bisogno di passare non solo l'ID utente, ma l'identificatore della risorsa protetta (l'id del post, forum, ecc.) Al contesto di sicurezza, che probabilmente non dovrebbe interessare a queste cose (è corretto?)

Se c'è un Security BC e vuoi che gestisca quella logica, non deve sapere che cos'è un forum in dettaglio ma:

  • Potrebbe semplicemente conoscere concetti come "moderato da" e concedere o negare i diritti di accesso di conseguenza.
  • È possibile disporre di una logica dell'adattatore che si iscrive agli eventi del dominio principale e li traduca in coppie di valori-chiave semplici (risorsa, utente autorizzato) che il BC BC di sicurezza può archiviare e utilizzare.

Poiché entrambe le risposte sono utili e più o meno indicano la stessa direzione, le ho votate entrambe. Ho accettato questo, poiché @ guillaume31 ha più o meno risposto alla mia domanda sull'implementazione di Vernon e continuerò con la mia implementazione basata sul suo suggerimento sull'uso delle risorse nel Security BC.
LittlePilgrim,

Devo dire che penso questo nel pieno opposto della mia risposta.
Ewan,

1
Forse sono troppo confuso ormai, ma la mia interpretazione era (per entrambe le risposte): 1. Tenere le preoccupazioni di sicurezza fuori dal dominio e usare il BC di sicurezza come servizio 2. Chiamare il servizio prima di invocare qualsiasi oggetto di dominio 3. Il servizio eseguirà il mapping da utenti / acl a moderatori, autori, ecc. moderator = securityService.GetModerator(userId, forumId) 4. La logica del dominio verrà implementata in questi oggetti come in moderator.EditPost () 5. Metodi come EditPost non sapranno nulla sui concetti di sicurezza, non ci saranno controlli aggiuntivi lì
LittlePilgrim,

Sto ancora cercando risposte / indicazioni su questo, ma ho scoperto che qualsiasi logica di autorizzazione che si basa sullo stato corrente dell'oggetto (come se sia attualmente assegnato a un moderatore) è in realtà una logica aziendale che appartiene a il tuo dominio e inoltre che se non è nel tuo dominio rischi di finire in uno stato non valido se il modello può essere aggiornato contemporaneamente. Ad esempio, se si convalida la proprietà utilizzando una politica e poi si va ad aggiornare quell'oggetto - in molti domini la proprietà è soggetta a modifiche e l'azione potrebbe non essere più valida.
Giordania,

A meno che tu non abbia un contesto collaborativo molto complesso, puoi probabilmente permetterti di implementare qui un modello di concorrenza ottimistica usando il versioning, ma se i tuoi controlli non vengono eseguiti all'interno o almeno contro una particolare istanza aggregata, i tuoi controlli potrebbero non essere coerenti con l'effettivo stato dell'oggetto entro il momento in cui si persistono le modifiche.
Giordania,

5

Autenticazione e autorizzazione è un cattivo esempio per DDD.

Nessuna di queste cose fa parte di un dominio a meno che la tua azienda non crei prodotti di sicurezza.

Il requisito aziendale o di dominio è o dovrebbe essere "Richiedo l'autenticazione basata sul ruolo"

Quindi si controlla il ruolo prima di chiamare una funzione di dominio.

Laddove hai requisiti complessi come "Posso modificare i miei post ma non altri", assicurati che il tuo dominio separi la funzione di modifica EditOwnPost()e EditOthersPost()che tu abbia una semplice funzione per la mappatura dei ruoli

È anche possibile separare la funzionalità in oggetti di dominio, come ad esempio Poster.EditPost()e Moderator.EditPost()questo è un approccio più OOP, anche se la scelta può dipendere dal fatto vostro metodo è in un dominio del servizio o di un oggetto di dominio.

Tuttavia, si sceglie di separare il codice che verrà eseguito il mapping dei ruoli al di fuori del dominio. quindi ad esempio se hai un controller webapi:

PostController : ApiController
{
    [Authorize(Roles = "User")]
    public void EditOwnPost(string postId, string newContent)
    {
        this.postDomainService.EditOwnPost(postId, string newContent);
    }

    [Authorize(Roles = "Moderator")]
    public void EditOtherPost(string postId, string newContent)
    {
        this.postDomainService.EditOtherPost(postId, string newContent);
    }
}

Come si può vedere, anche se la mappatura ruolo viene eseguita sullo strato di hosting, il complesso logica di ciò che costituisce modificare il proprio o un altro post fa parte del dominio.

Il dominio riconosce la differenza delle azioni, ma il requisito di sicurezza è semplicemente che "la funzionalità può essere limitata dai ruoli" .

Questo è forse più chiaro con la separazione degli oggetti di dominio, ma essenzialmente si sta verificando il metodo che costruisce l'oggetto invece del metodo che chiama il metodo di servizio. Il tuo requisito, se vuoi ancora esprimerlo come parte del dominio diventerebbe "solo i moderatori possono costruire l'oggetto moderatore"


4
Controllare il ruolo "staticamente" è un po 'semplicistico. Cosa succede se un moderatore non è autorizzato a modificare il post di un altro moderatore? Questo controllo non dovrebbe far parte del dominio?
Réda Housni Alaoui,

2
@ RédaHousniAlaoui Mi sto chiedendo anche questo. Non riesco a pensare a un modo per gestirlo se non quello di includere qualche menzione di Utenti / Moderatori nel dominio o eseguire una sorta di logica all'interno di quel ApiController per ottenere il ruolo dell'autore del post. Nessuno di questi sembra giusto, e questa è una cosa abbastanza comune nella mia esperienza che una guida chiara sarebbe estremamente utile.
Jimmy,

1
@Erwan, il caso d'uso di cui sto parlando è dinamico. Basare la frase "Autenticazione e autorizzazione è un cattivo esempio per DDD" su ciao esempi del mondo è disonesto. DDD è qui per evitare la complessità accidentale e consentire di gestire la complessità del dominio. Le autorizzazioni dinamiche non sono una complessità accidentale né qualcosa che non accade nella vita reale.
Réda Housni Alaoui,

1
IMHO, il problema con la tua soluzione è che non soddisfa il cliente. Il cliente spesso desidera poter cambiare dinamicamente tali relazioni. Inoltre, questo è anche ciò che accade quando un fornitore fornisce lo stesso software aziendale a diverse aziende. Se il software è scarsamente ottimizzabile, il fornitore alla fine morirà.
Réda Housni Alaoui,

1
"Ma è generalmente riconosciuto come una" cosa negativa "le impostazioni di sicurezza diventano ingestibili nel tempo, il che significa che la tua app diventa insicura." Con la progettazione e il test corretti, è totalmente gestibile. Ma, dal mio XP, per produrre il progetto corretto, il dominio deve verificare l'autorizzazione. L'alternativa è l'utopia.
Réda Housni Alaoui,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.