2013-07-01 11 views
10

Sto cercando di utilizzare il framework Apache Shiro per proteggere la mia applicazione Web (l'interfaccia utente è basata su Vaadin 6). Ho esaminato tutti gli esempi sul sito di Shiro e anche cercato su google per ore, ma non riesco a trovare un modo pulito per gestire i seguenti requisiti.Come gestire i ruoli/permessi gerarchici usando Apache Shiro?

Supponendo che l'applicazione sia una specie di strumento di gestione del progetto, in cui gli utenti creano attività, che appartengono a particolari reparti della gerarchia aziendale. Ogni utente può lavorare in più dipartimenti e ha ruoli di sicurezza diversi in ogni dipartimento. Esempio:

 
Department A  - User is 'Manager' here 
Department B 
    Department C  - User is 'Admin' here 
    Department D 

Utente 'Manager' nel Reparto A utente è 'admin' in C utente deve anche ereditare il ruolo 'Admin' per il reparto D (che è antenato di C).

Quindi, controllo il permesso di base (supponendo che voglio visualizzare l'attività appartenente a qualche dipartimento) sarebbe quello di:

  1. Verificare se l'utente l'attività sta cercando di vista appartiene all'utente reparto ha un ruolo nella;
  2. Verificare che l'utente abbia richiesto l'autorizzazione in base al proprio ruolo in questo reparto.

Sono attualmente bloccato nella comprensione di come implementare non solo il concetto di "system wide role", ma "role in this department particolare".

Come posso trasformare l'esempio precedente in stringa di autorizzazione come "attività: vista: 123"? E come controllerò l'autorizzazione nella mia logica aziendale?

Un altro dubbio è l'implementazione con Shiro, mi piacerebbe utilizzare una soluzione pronta all'uso che comporterà il minimo sforzo per fornire le mie implementazioni. Tuttavia, sembra che le implementazioni incorporate di Shiro siano progettate solo per casi semplici. C'è un esempio di implementazione di autorizzazione complessa per iniziare (che può coprire il caso precedente)?

risposta

3

Voglio solo descrivere la mia soluzione a questo problema, che può essere utile a qualcuno. Ritengo che questo potrebbe non essere ottimale, quindi ancora aperto a qualsiasi suggerimento su un'implementazione più pulita.

Supponendo che ho bisogno di fissare le seguenti azioni:

  • attività: edit
  • Attivita: Vedi

E ho anche bisogno di assicurarsi che le autorizzazioni non di sistema sono ampie, ma dipende sul mio ruolo in particolare dipartimento. Quello che ho fatto è esplicitamente permesso 'dipendente dal dipartimento' per l'utente nel mio Reame. Esempio (vedi gerarchia nel post):

  • DEP_A: Attivita: Vedi
  • DEP_C: Attivita: Vedi
  • DEP_C: Attività: modificare

Ogni volta che voglio verificare se l'azione contro alcune attività è consentito o meno, sto creando un elenco di autorizzazioni da controllare.Esempio:

L'attività A appartiene al reparto D, voglio "vederlo". Permessi per controllare saranno:

  • DEP_D: Attivita: Vedi
  • DEP_C: Attivita: Vedi
  • DEP_B: Attivita: Vedi

Se sto Admin nel reparto C, lo farei avere il permesso 'DEP_C: activity: view' e quindi il controllo verrà passato. Questo consente di implementare l'ereditarietà dei diritti nella gerarchia della struttura aziendale.

Ecco il codice snipplet dalla mia classe di servizio responsabile per i controlli delle autorizzazioni:

@Override 
    public void checkIfOperationPermitted(SecurityOperation operation, 
     Object object) 
    { 
     final Subject currentUser = SecurityUtils.getSubject(); 

     if(currentUser.isPermitted(
     SecurityOperation.SYSTEM_ADMIN.getPermissionString()) || 
     currentUser.hasRole("admin")) 
     { 
     // no need to check anything else, 
     // admin is system wide role. 
     return; 
     } 

     if(object instanceof Activity) 
     { 
     // Activity permissions fully depends on organization and 
     // product hierarchies. PermissionResolver is just a class 
     // which generates list of permission strings based on 
     // department activity is belonging to. 
     Activity a = (Activity) object; 
     List<String> permissionsToCheck = 
      permissionResolver.resolveHierarchicalPermissions(operation, a); 
     boolean permitted = false; 
     for(String permission: permissionsToCheck) 
     { 
      if(currentUser.isPermitted(permission)) 
      { 
       permitted = true; 
       break; 
      } 
     } 
     if(!permitted) 
     { 
      throw new UnauthorizedException("Access denied"); 
     } 
     } 
     else 
     { 
     // Check for system wide permissions 
     currentUser.checkPermission(operation.getPermissionString()); 
     } 
    } 

Un altro modo in cui stavo pensando è aggiungere tutti tali permessi per l'utente nel mio regno, ma ha rifiutato questa gerarchia in quanto azienda può in generale contiene N livelli - che aumenta notevolmente la duplicazione nell'elenco delle autorizzazioni per un particolare utente (utilizzo della memoria).

Problemi correlati