Pratiche standard per il controllo degli accessi (modello di progettazione)


9

Sto guardando il mio design dell'interfaccia e sto lottando per decidere quale sia il modo più "corretto" per implementare il controllo degli accessi in base al ruolo, dato un usere un a subjectcui uservorrebbe accedere.


Per quanto posso vedere, ho tre opzioni fondamentali (una quarta è una bastardizzazione delle prime tre e una quinta è una modifica della quarta):

  1. Esegui subjectuna query con un elenco di autorizzazioni che userha -subject.allowAccess(user.getPermissionSet)
  2. Esegui useruna query con un elenco di autorizzazioni subjectnecessarie per:user.hasPermissionTo(subject.getRequiredPermissions())
  3. Interroga una terza parte per individuare le intersezioni delle autorizzazioni - accessController.doPermissionSetsIntersect(subject.permissionSet, user.getPermissionSet())
  4. Eseguire una query su subject/ user, mentre si delega la "decisione" a una classe di terze parti
  5. Cerca userdi accedere a subjecte genera un errore se l'accesso non è consentito

Mi sto avvicinando all'opzione quattro: chiedi al campo di subjectcontenere un accessControllercampo, dove chiamate a subject.userMayAccess(User user)delegare l'operazione alla la:

class Subject {
    public function display(user) {
        if(!accessController.doPermissionSetsIntersect(this.permissionSet, user.getPermissionSet())) {
            display403(); //Or other.. eg, throw an error..
        }
    }
}

.. ma poi questo solleva ulteriori domande:

  • dovrebbe accessControlleressere un campo vs una classe statica ..?
  • Dovrebbe subject sapere quali autorizzazioni sono necessarie per poterlo visualizzare?
  • dove entra in gioco il principio della minima conoscenza, rispetto alla chiamata subject.display()? I chiamanti dovrebbero subject.display()mai sapere che il controllo degli accessi è attivo? (dov'è subject.display()un "metodo modello" finale)
  • hanno subject.display()gestire il controllo di accesso, un'eccezione in cui l'utente non ha l'autorizzazione richiesta?

Quale sarebbe considerata la "migliore pratica" in questa situazione? Dove dovrebbe effettivamente verificarsi la responsabilità di eseguire i controlli?

Poiché si tratta in qualche modo sia di un esercizio accademico che progredirà nell'implementazione, i riferimenti ai modelli di progettazione sarebbero apprezzati.

Risposte:


7

La migliore pratica consiste nell'utilizzare qualcosa noto come modello di intercettore per intercettare le chiamate verso aree protette.

Ciò può essere ottenuto utilizzando AOP o preoccupazioni trasversali applicate ai punti di accesso.

Il soggetto non dovrebbe mai sapere chi è in grado di vederlo. Ciò complica inutilmente il codice soggetto e non vi è motivo per richiederlo, a meno che non si fornisca inavvertitamente un meccanismo di accesso diretto alla stessa funzione.

Preferibilmente il chiamante e il chiamante non dovrebbero conoscere l'accesso, a parte la gestione dei rifiuti. Tuttavia, il problema dipenderà dal sistema su cui si sta implementando e da come si ottiene l'accesso alle credenziali / entità di sicurezza per il chiamante. Ad esempio, nei sistemi SOAP queste informazioni vengono aggiunte all'intestazione di un messaggio SOAP, mentre in un sistema Windows sarebbero disponibili tramite il meccanismo di autenticazione di Windows.

Se si utilizza l'approccio AOP o l'interceptor pattern, genererebbe tutte le eccezioni necessarie e spetterà al client (chiamante) gestire eventuali eccezioni generate.

In questo modo mantieni separato il tuo client, servizio e codice di autenticazione senza mescolare conoscenza o funzionalità.



2

Credo che l'opzione 3 è il più vicino, ma invece di interrogare il usere subjectsui loro set di autorizzazioni si deve passare l' usere subjectal controller di accesso.

class Subject {
    public function display(user) {
        if(!accessController.checkAccess(this, user, AccessControl.Read)) {
            display403(); //Or other.. eg, throw an error..
        }
    }
}

Il controller di accesso dovrebbe essere responsabile sia per ottenere i set di autorizzazioni sia per verificare se l'accesso è sufficiente. In questo modo si isolano sia la logica di archiviazione che la logica di controllo nel controller di accesso, separate sia dall'utente che dall'oggetto.

L'altro elemento eventualmente mancante nel tuo esempio è quale operazione viene eseguita. Alcuni utenti potrebbero avere il diritto di leggere alcuni dati, ma non aggiornare, cancellare, eseguire, ecc Quindi, si potrebbe avere un checkAccessmetodo sul controller di accesso con tre parametri: user, subject, operation. Potresti anche fornire alcune informazioni aggiuntive checkAccessper restituire informazioni sul motivo per cui l'accesso non è stato concesso.

Ad esempio, delegare tutto ciò al controller di accesso in un secondo momento consente di sostituire il modo in cui sono rappresentate le autorizzazioni. È possibile iniziare con il controllo degli accessi in base al ruolo e passare successivamente alle attestazioni. È possibile memorizzare le autorizzazioni in una struttura semplice per cominciare e successivamente aggiungere gruppi / ruoli gerarchici e operazioni consentite su diversi tipi di argomenti. Non mettere i set di permessi nell'interfaccia aiuta a abilitare questo.

A mio avviso, se si utilizza AOP o un codice di tipo boilerplate per collegarlo, è meno importante.

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.