Progettazione: come gestire le autorizzazioni utente su un sistema

5

Il mio team sta attualmente lavorando su un massiccio refactoring di un'applicazione di medie dimensioni in PHP. Stiamo facendo del nostro meglio per ridefinire il nostro codice su una base di moduli (ordini, utenti, prodotti). Il problema che mi sto attualmente ponendo riguarda la gestione di ciò che un utente è autorizzato a fare sul nostro sistema.

Attualmente, questo dipende principalmente dal Livello di accesso dell'utente al nostro sistema. A volte, potremmo dover fare riferimento al loro gruppo proprietario per vedere se il gruppo di livello superiore è autorizzato a fare qualcosa (effettuare un ordine) e passare tale autorizzazione in transito all'utente.

Quello che ho scoperto finora è una classe chiamata "Guardian". Guardian accetta un utente e quindi ha funzioni come "canPlaceOrder" o "canViewOrderReport". Un vantaggio di questo approccio è che siamo in grado di vedere tutte le azioni sul nostro sistema che richiedono autorizzazioni in un unico posto. Inoltre, ciò ci consentirà di separare la nostra logica di autorizzazione dai nostri modelli di front-end e di dominio.

Tuttavia, ho potuto vedere questa non essendo una soluzione completamente scalabile. Seguendo il principio OOP che una classe dovrebbe essere aperta per estensione, chiusa per la modifica, posso vedere che aggiungendo più autorizzazioni al nostro sistema, la nostra classe Guardian dovrà aggiungere anche altri metodi.

Mi piace il vantaggio di avere tutte le nostre autorizzazioni ben definite in un modo leggibile dall'uomo usando una classe, in modo che sappiamo sempre che stiamo controllando i criteri corretti. Tuttavia, sono preoccupato per la scalabilità. Ci sono altri approcci a questo problema?

La mia domanda è veramente: qual è un buon modo per gestirlo? La mia soluzione va bene?

    
posta xJoshWalker 05.03.2015 - 14:30
fonte

4 risposte

1

ci sono molti buoni modi.

Potresti implementare open-closed usando sempre una factory per ottenere il Guardian e restituire un sottotipo di guardian che eredita la versione precedente. Nuova funzionalità potrebbe trasmettere al sottotipo più recente.

Potresti anche implementare open-closed solo ... Aggiungendo metodi! E sapendo di non toccare gli altri. Mentre questo è più facile da rovinare, sì, devi sapere cosa stai facendo. Sfortunatamente uno sviluppatore che non sa cosa sta facendo, rovinerà il metodo menzionato in precedenza (più comunemente citato come metodo per implementare open-closed).

Potresti anche creare un elenco di tipi di base 'permessi'. Wireup / avvio popolerebbe la lista con oggetti. Quindi potresti semplicemente aggiungere autorizzazioni ereditate. Per eseguire una query, il codice più recente è in grado di cercare nell'elenco il suo sottotipo e chiamarlo.

Ad esempio in .net potresti persino creare un metodo (debole sul PHP qui, ma non provare a compilare questo): bool GetPermission () {  return (da p in _permissionList.OfType) .First (); }

Utilizzo:  can_do_this = GetPermission () NeedManagerApproval ();.

E ... ci sono molti altri modi.

Sì, questo è un aspetto / preoccupazione trasversale. Ma ...

Penso che un modo sbagliato potrebbe essere quello di aggiungere un framework AOP al tuo progetto

    
risposta data 06.03.2015 - 03:06
fonte
2

Il guardiano shold ha un

public boolean checkPermission(String permissionTag, int userID);

metodo.

In questo modo il tutore non deve cambiare quando vengono a crearsi nuovi permessi.

Uso

if (guardian.checkPermission("PLACE_ORDER",loggedUser)) {
    // place order
}
    
risposta data 05.03.2015 - 14:41
fonte
0

La soluzione è a posto.

La sicurezza e l'accessibilità sono pervasive nel sistema, quindi è necessario aggiungere metodi poiché le autorizzazioni vengono aggiunte è fattibile.

Utilizzare le stringhe di caratteri per identificare le autorizzazioni va bene in un programma PHP poiché non scoprirai mai che il tuo codice è sbagliato fino all'ora di esecuzione. Anche le stringhe di caratteri possono essere composte:

if ( guardian.checkPermissions(["PLACE_ORDER", "MODIFY_ORDER"]) ) {
  // place a modified order
}
    
risposta data 05.03.2015 - 14:51
fonte
0

La mia preoccupazione per la tua soluzione sarebbe il sovraccarico di mantenere le autorizzazioni degli utenti, a seconda del numero di utenti che hai e del fatturato degli utenti.

Ogni volta che ottieni un nuovo utente, devi aggiungere una serie completa di autorizzazioni "canViewProduct", "canViewOrders", "canPlaceOrder" ecc. ecc.

Nei negozi più grandi di solito questo è gestito dividendo il problema in due.

Crei "ruoli", ad es. "manager", "retailCustomer", "wholeSaleCustomer", "badCreditCustomer".

Quindi assegni le permissioni atomiche a questi ruoli.

Quando ottieni un nuovo utente, assegni semplicemente uno o due ruoli. Quando decidi che è necessario limitare "badCreditCustomers" per incassare la consegna, basta semplicemente rimuovere "canOrderOnCredit" da quel ruolo.

    
risposta data 06.03.2015 - 03:20
fonte