2012-01-02 15 views
21

Próbuję zrozumieć podstawy bezpieczeństwa Java i AccessController.doPrivileged() Wykorzystanie Zacząłem przykładowy programAccessController Wykorzystanie

import java.security.AccessController; 
import java.security.PrivilegedAction; 
public class AccessSystemProperty { 
    public static void main(String[] args) { 
    System.out.println(System.getSecurityManager()); 
     AccessController.doPrivileged(
     new PrivilegedAction<Boolean>(){ 
      public Boolean run(){ 
       System.out.println(System.getProperty("java.home")); 
       return Boolean.TRUE; 
      } 
     } 
     ); 
    } 
} 

jeśli próbuję uruchomić powyższy kod bezpieczeństwa przy użyciu domyślnego zarządzać Dostaję AccessControlException Moja StackTrace jest

C:\>java -Djava.security.manager AccessSystemProperty 
[email protected] 
Exception in thread "main" java.security.AccessControlException: access denied (
java.util.PropertyPermission java.home read) 
     at java.security.AccessControlContext.checkPermission(Unknown Source) 
     at java.security.AccessController.checkPermission(Unknown Source) 
     at java.lang.SecurityManager.checkPermission(Unknown Source) 
     at java.lang.SecurityManager.checkPropertyAccess(Unknown Source) 
     at java.lang.System.getProperty(Unknown Source) 
     at AccessSystemProperty$1.run(AccessSystemProperty.java:9) 
     at AccessSystemProperty$1.run(AccessSystemProperty.java:8) 
     at java.security.AccessController.doPrivileged(Native Method) 
     at AccessSystemProperty.main(AccessSystemProperty.java:6) 

uprzejmie mi pomóc, aby uzyskać jasny obraz

1) kiedy potrzebujemy użyć AccessController.doPrivileged()?. (jeżeli SecurityManager jest obecny, używamy AccessController.doPrivileged, dlaczego to się nie udaje w powyższym przykładzie) 2) jaka jest prawdziwa korzyść, którą uzyskujemy za pomocą AccessController i PrivilegedAction ?. 3) Czy potrzebujemy niestandardowego pliku zasad, aby powyższy przykład zadziałał? Dzięki Paul

Odpowiedz

26

byłoby użyć AccessController.doPrivileged(), aby dać pewne przywileje kodu, które wcześniej kodu wywołującego w stosie nie ma, ale które uprzywilejowane kody ma mocy tego przywileju jest przyznawana w polityce.

Załóżmy na przykład, że ClassA wywołuje metody w ClassB, a ClassB musi przeczytać właściwość systemową java.home (aby wypożyczyć z twojego przykładu) i założyć, że wskazałeś, że SecurityManager jest obecny na twoim przykładzie.

Zakładamy również, że ClassB jest ładowany ze słoika nazwie „classb.jar” (ale aby przykładową pracę ClassA nie jest załadowany z tego słoika), następujące powinny być w pliku zasad bezpieczeństwa:

grant codeBase "file:/home/somebody/classb.jar" { 
    permission java.util.PropertyPermission "java.home", "read"; 
}; 

Teraz, gdy klasa B działa i próbuje wykonać System.getProperty(), która NIE jest zapakowana w AccessController.doPrivileged() w "java.home". menedżer bezpieczeństwa sprawdzi stos, aby zobaczyć, czy każda klasa wyższa na stosie ma właściwość PropertyPermission (bezpośrednio lub domyślnie) dla "java.home". Jeśli nie, dostęp zakończy się niepowodzeniem.

Jednakże, jeśli ClassB zawija System.getProperty() w AccessController.doPrivileged(), securitymanager dba tylko o to, że plik profilu daje ClassB ten przywilej, a więc dostęp jest dozwolony.

Oto fragment pokazać to:

public void doStuff() { 

    try { 
     /* 
     * this will fail even if this class has permission via the policy file 
     * IF any caller does not have permission 
     */ 
     System.out.println(System.getProperty("java.home")); 
    } catch (Exception e1) { 
     System.out.println(e1.getMessage()); 
    } 
    AccessController.doPrivileged(new PrivilegedAction<Boolean>() { 
     public Boolean run() { 
      try { 
       /* 
       * this will be allowed if this class has permission via the policy 
       * file even if no caller has permission 
       */ 
       System.out.println(System.getProperty("java.home")); 
      } catch (Exception e) { 
       System.out.println(e.getMessage()); 
      } 

      return Boolean.TRUE; 
     } 
    }); 

Tak więc w przypadku Twojej przykład wystarczy podać plik zasad zawierający coś podobnego do strofy grant że mowa powyżej.

+0

Cześć Rob, dzięki za tak jasne i szczegółowe wyjaśnienie. Zawsze próbowałem z klasy pojedynczej, więc nie byłem w stanie rozgryźć różnicy. Kiedy włączamy domyślny menedżer bezpieczeństwa (przy użyciu -Djava.security.manager) czy istnieje jakiś plik zasad, który jest używany do ograniczania dostępu? (Który jest częścią JDK) <"> "menedżer bezpieczeństwa sprawdzi stos, aby zobaczyć, czy każda klasa wyżej na stosie ma właściwość PropertyPermission ". <"> Tutaj odnoszą się StackTraceElement [] z Thread.currentThread(). GetStackTrace(); Albo pamięć Stack? Czy mógłbyś wyjaśnić to trochę? –

+0

@PaulErric domyślne pliki zasad są zdefiniowane w pliku java.security i są (zwykle) policy.url.1 = file: $ {java.home} /lib/security/java.policy policy.url.2 = file : $ {user.home} /. java.policy. Ten link ma więcej: http://docs.oracle.com/javase/1.4.2/docs/guide/security/PolicyFiles.html#DefaultImpl.Przez stos rozumiem sekwencję wywołującą metody, które można zobaczyć w układach stacktraceelements. –