Implementazione DDD: utenti e permessi

8

Sto lavorando su una piccola applicazione cercando di cogliere i principi del design basato sul 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 cercando di implementare un forum di discussione simile e semplice. Ho anche controllato gli esempi IDDD su github. Ho delle difficoltà nell'adottare l'identità e l'accesso al mio caso. Consentitemi di fornire alcune informazioni di base:

  • I (si spera) comprendano il ragionamento alla base della separazione della logica degli utenti e delle autorizzazioni: si tratta di 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 e il Moderatore.
  • Le operazioni di dominio vengono chiamate con un ruolo correlato come parametro: ad esempio:

    ModeratePost( ..., moderator);

  • Il metodo dell'oggetto dominio controlla se la data istanza di Moderatore non è nullo (l'istanza di Moderatore sarà nullo se l'utente ha chiesto dal contesto Identità e Accesso non ha il ruolo di Moderatore).

  • In un caso, esegue 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 si fondono nuovamente nel dominio principale? Precedentemente i libri affermavano "con chi può pubblicare un argomento, o con quali condizioni è permesso: un forum ha solo bisogno di sapere che un autore lo sta facendo in questo momento".

  • L'implementazione basata sul ruolo nel libro è abbastanza semplice: quando un moderatore è il dominio principale prova a convertire l'ID utente corrente in un'istanza di Moderatore o in un Autore quando ne ha bisogno. Il servizio risponderà con l'istanza appropriata o un 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 progetto attuale di cui sto pilotando ha un modello piuttosto complesso con gruppi, ACL, ecc.

Anche con regole che non sono molto complesse, come: "Un post deve essere modificato solo dal suo proprietario o da un editor", questo approccio sembra non funzionare, o almeno non vedo il modo corretto di implementare esso.

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

Estraendo le autorizzazioni dal dominio principale e controllandole nei metodi degli oggetti di dominio o nei servizi, finirei al punto di partenza: mescolare i problemi di sicurezza con il dominio.

Ho letto da qualche parte (e sono tendenzialmente d'accordo) che queste cose legate al permesso non dovrebbero far parte del dominio principale, a meno che la sicurezza e le autorizzazioni non siano il dominio principale stesso. Una semplice regola come quella sopra citata giustifica che la sicurezza fa parte del dominio principale?

    
posta LittlePilgrim 14.03.2018 - 16:26
fonte

2 risposte

3

A volte è difficile distinguere tra regole di controllo degli accessi reali e invarianti di dominio che limitano il controllo degli accessi.

Soprattutto, le regole che dipendono dai dati disponibili solo nel corso di una particolare parte della logica di dominio potrebbero non essere facilmente estraibili dal dominio. Solitamente, il Controllo di accesso viene chiamato prima o dopo l'esecuzione di un'operazione di dominio ma non durante.

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

I would need to pass not just the userId, but the identifier of the protected resource (the id of the post, forum, etc.) to the security context, which probably should not care about these things (is it correct?)

Se c'è un Security BC e vuoi che gestisca quella logica, non è necessario sapere cosa è un Forum nei dettagli, ma:

  • Potrebbe semplicemente avere conoscenza di concetti come "moderato da" e concedere o negare i diritti di accesso di conseguenza.
  • È possibile avere una logica dell'adattatore che sottoscriva gli eventi del dominio principale e li traduca in coppie di valori chiave semplici (risorse, autorizzatiUtenti) per la sicurezza BC da memorizzare e utilizzare.
risposta data 15.03.2018 - 09:44
fonte
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 per la sicurezza.

Il requisito Business o dominio è, o dovrebbe essere, "Richiedo l'autenticazione basata sui ruoli"

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

Se hai requisiti complessi come "Posso modificare i miei post ma non gli altri", assicurati che il tuo dominio separi la funzione di modifica in EditOwnPost() e EditOthersPost() in modo da avere una semplice funzione per il mapping dei ruoli

Puoi anche separare la funzionalità in Oggetti Dominio, come Poster.EditPost() e Moderator.EditPost() , questo è un approccio più OOP, sebbene la tua scelta dipenda dal fatto che il tuo metodo sia in un Servizio di Dominio o un Oggetto Dominio.

Tuttavia, se si sceglie di separare il codice, la mappatura del ruolo avverrà 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 puoi vedere anche se la mappatura dei ruoli viene eseguita sul livello di hosting, la logica complessa di ciò che costituisce la modifica del tuo proprio o di un altro post è 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 del dominio, ma essenzialmente si sta controllando il metodo che costruisce l'oggetto al posto del metodo che chiama il metodo di servizio. Il tuo requisito, se vuoi ancora doppiarlo come parte del dominio diventerebbe 'solo i moderatori possono costruire l'oggetto moderatore'

    
risposta data 14.03.2018 - 17:15
fonte