2013-07-01 12 views
10

Próbuję użyć frameworka Apache Shiro do zabezpieczenia mojej aplikacji internetowej (interfejs oparty jest na Vaadin 6). Przejrzałam wszystkie przykłady na stronie Shiro, a także googlowałem przez wiele godzin, ale nie mogę znaleźć prostego sposobu na spełnienie następujących wymagań.Jak radzić sobie z hierachicznymi rolami/uprawnieniami za pomocą Apache Shiro?

Założenie aplikacji jest rodzajem narzędzia do zarządzania projektami, w którym użytkownicy tworzą działania, które należą do poszczególnych działów w hierarchii firmy. Każdy użytkownik może pracować w kilku działach i ma różne role zabezpieczeń w każdym dziale. Przykład:

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

Użytkownik nie jest „Menedżer” w dziale A użytkownika to „Admin” w dziale C użytkownik powinien również dziedziczyć rolę „admin” za dział D (który jest przodkiem Działu C).

Więc podstawowy check pozwolenie (zakładając, że chcę zobaczyć aktywność należącej do jakiegoś działu) byłoby:

  1. Sprawdź, czy użytkownik aktywność próbuje widzenia należy do użytkownika department odgrywa rolę w;
  2. Sprawdź, czy użytkownik ma wymagane pozwolenie w oparciu o jego rolę w tym dziale.

W tej chwili utknąłem w zrozumieniu, w jaki sposób wdrożyć nie tylko "rolę całego systemu", ale także "rolę w tym konkretnym dziale".

Jak mogę przekonwertować powyższy przykład na ciąg uprawnień, taki jak "activity: view: 123"? I jak mogę sprawdzić pozwolenie w mojej logice biznesowej?

Jeszcze jedna wątpliwość to implementacja z Shiro, chciałbym użyć jakiegoś nieszablonowego rozwiązania przy minimalnych wysiłkach związanych z dostarczaniem własnych implementacji. Wydaje się jednak, że wbudowane implementacje Shiro są przeznaczone tylko do prostych przypadków. Czy istnieje przykład złożonej autoryzacji na początek (która może obejmować powyższy przypadek)?

Odpowiedz

3

Chciałbym tylko opisać moje rozwiązanie tego problemu, które może być przydatne dla kogoś. Uważam, że może to nie być optymalne, więc nadal otwarte na wszelkie sugestie dotyczące czystszej realizacji.

Zakładając muszę zabezpieczyć następujące czynności:

  • aktywność edytuj
  • działalność: widok

I ja też należy upewnić się, że uprawnienia nie systemu są szerokie, ale zależy o mojej roli w danym dziale. To, co zrobiłem, to jednoznacznie dodane uprawnienie "zależne od działu" dla użytkownika w mojej sferze. Przykład (patrz hierarchię w poście):

  • DEP_A: działalność: widok
  • DEP_C: działalność: widok
  • DEP_C: działalność: edytować

każdym razem, gdy chcesz sprawdzić, czy działanie aby niektóre działania były dozwolone lub nie, tworzę listę uprawnień do sprawdzenia.Przykład:

Aktywność A należy do Departamentu D, chcę ją "wyświetlić". Uprawnienia do sprawdzenia będą:

  • DEP_D: działalność: widok
  • DEP_C: działalność: widok
  • DEP_B: działalność: widok

Jeśli jestem Administrator w dziale C, chciałbym mieć uprawnienie "DEP_C: aktywność: widok", a zatem sprawdzanie zostanie zaliczone. To pozwala implementować dziedziczenie uprawnień w hierarchii struktury firmy.

Oto snipplet kod z mojej klasy usług odpowiedzialny za kontrolę uprawnień:

@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()); 
     } 
    } 

Innym sposobem Myślałam o to dodać wszystkie takie uprawnienia dla użytkownika w moim królestwie, ale odmówił tym od firmy hierarchii może w ogólne zawierają poziomy N - co znacznie zwiększa duplikację na liście uprawnień dla konkretnego użytkownika (wykorzystanie pamięci).

Powiązane problemy