Webstart + externe/lokale Plugins/JARS einbinden

benhaze

Mitglied
Hallo liebe Freunde der Entwicklung!

Ich habe folgendes Problem:

Ich möchte meine Webstart-Anwendung so erweitern, das es möglich ist lokale JARs als Plugin einzubinden.

Das Ganze mache mit dem dem URLClassLoader.
Klappt als Standalone-App (also NICHT via Webstart) auch problemslos.

Als Webstart-App allerdings bekomme ich eine *access denied exception*, sobald das lokale JAR irgendwelche Security-Relevanten Dinge tut (z.B Systemvariablen auslesen).

Die liegt mit Sicherheit am Security-Context und der JNLP-Datei.
Die JNLP-Datzei kennt das Plugin/JAR nicht und dementsprechend hat:
Code:
    <security>
        <all-permissions/>
    </security>
keine Wirkung bei dieser JAR.

Kennt jemand eine Möglichkeit, wie ich dieses lokale JAR dem SecurtiyManager-Context hinzufügen kann?

Ich dachte da an etwas wie:
Code:
com.sun.javaws.security.AppPolicy.getInstance().addPermissions()
oder
JNLPClassLoaderUtil.getInstance().addResource

Aber leider hatte ich bisher keinen Erfolg, da das Interface (für mich) nicht genügend dokumentiert ist.
Die AccessDenied exception bleibt.

In der AppPolicy.java habe ich folgendes gefunden:

Java:
// Get LaunchDesc for for the JARDesc.
        LaunchDesc ld = null; 
        int access = LaunchDesc.SANDBOX_SECURITY; 
    boolean trusted = false;
        // jd will not have parent if it was not in jnlp file 
        if (jd.getParent() != null) { 
            ld = jd.getParent().getParent(); 
            access = ld.getSecurityModel();         
        }

Es sieht so aus, wenn eine JAR nicht in der JNLP steht, bekommt diese nur SANDBOX-SECURTIY.

Meine Frage nun: Wie kann ich das ändern?
 

benhaze

Mitglied
Wenn ich die JAR-Datei nicht signiere, erhalte ich die Meldung:
Code:
Ihre Anwendung enthält unsignierten und signierten Code, trozdem ausführen? JA/NEIN
Wenn ich die Datei signiere, dann erscheint dieser Dialog nicht.

Der Fehler mit dem access-denied kommt aber trotzdem.

Das Signieren alleine bringt demzufolge nichts.

In meinem ersten Post habe ich das bereits geschrieben und Code gepostet, warum das scheinbar so ist.
Das Problem: meine JAR-Datei ist nicht Bestandteil der JNLP.
Daher nur: SANDBOX_SECURITY
 
Zuletzt bearbeitet:

benhaze

Mitglied
Folgendes habe ich getan:

1. Webstart-Anwendung gestartet
2. lokale (aber signierte!) JAR-Datei in das System geladen (via UrlClassloader)
3. auf das Plugin zugegriffen

Das ist die Exception die auftritt, sobald eine Methode in meinem (nachgeladenen!) JAR versucht die Umgebungsvariable auszulesen:
Code:
access denied (java.lang.RuntimePermission getenv.APPDATA)
    java.security.AccessControlContext.checkPermission(Unknown Source)
    java.security.AccessController.checkPermission(Unknown Source)
    java.lang.SecurityManager.checkPermission(Unknown Source)
    java.lang.System.getenv(Unknown Source)
    de.benhaze.plugin.test.createHome(GlobalSystemProperties.java:235)
Wie ich schon angemerkt habe, ist den AppPolicy.java Kommentaren folgendes zu entnehmen (sinngemäß):

Wenn eine geladene JAR nicht in der JNLP deklariert wurde (unter Ressources), so wird für dieses JAR mit
SandBox-Securtity ausgeführt.


Irgendwie deutet Vieles darauf hin, das *standardmäßig* meine Plugin-JAR:
1.in der JNLP auftauchen muss
2.irgendwie vom Server stammen muss

Das müsste allerdings auch irgendwie anders möglich sein.

Dies war mein Ansatz:
Java:
    private void addJarToSecurityContext(URL p_url) 
    {
        if (!WebstartUtils.isWebstartApp())
            return;
        
        try
        {
            CodeSource cs = new CodeSource(p_url, (Certificate[])null);
            
            JNLPClassLoaderIf cl =  JNLPClassLoaderUtil.getInstance();
            cl.addResource(p_url, "1", null);
            
            PermissionCollection pc = new Permissions();
            Permission perm = new AllPermission();
            pc.add(perm);
            boolean ok = com.sun.javaws.security.AppPolicy.getInstance().addPermissions(pc, cs, true);
            System.out.println("adding jar to sec-context: " + ok);
        }
        catch(Exception p_ex)
        {
            ErrorViewer.showError(p_ex);
        }
    }
Hat allerdings nicht richtig funktioniert.
Wenn ich die JAR so dem Securtiy-Context hinzufüge, bekomme ich den Fehler (von JWS) das das JAR angeblich nicht gefunden wurde.
Dabei versucht JWS die URL mit den URLs aus der JNLP abzugleichen. (und findet die URL nicht)
 

benhaze

Mitglied
Dafür gibt es verschiedene Gründe:
- die Anwendung ist zweierlei verfügbar (Standalone + Webstart)
Ich möchte nicht unbedingt extra Code schreiben müssen, für beide Varianten (um die Plugins zu laden).
- der Client soll nicht unbedingt alle Plugins kennen (können)
- fällt mir keine passende Lösung ein, das mittels der JNLP zu lösen
(was ja nicht bedeuten soll, das es keine gibt)

Wenn es gar nicht geht (was ich mir nicht vorstellen kann), muss ich versuchen das irgendwie mit der JNLP-Datei zu machen.
Meine JNLP wird bereits mittels einer JSP generiert.
Ich muss mir das mit dem download=lazy mal genauer anschauen.
Möglichweise kann mir das irgendwie helfen.

-------------------------

Momentan habe ich das Problem, das es mir nicht (mehr) gelingt Webstart-Anwendung zu debuggen.
- Connection refused -
JWS startet einen neuen Prozess und leitet die JVM-Parameter nicht weiter.

Dieses Problem wurde auch hier besprochen:
(https://forums.oracle.com/forums/thread.jspa?threadID=1303538)
und
https://forums.oracle.com/forums/thread.jspa?messageID=5499355
 
Zuletzt bearbeitet:
G

Guest2

Gast
Moin,

ins Blaue: Hast Du es schon mal mit AccessController.doPrivileged versucht?

z.B. (wie im Beispiel):
Java:
somemethod() {
        ...normal code here...
        String user = (String) AccessController.doPrivileged(
          new PrivilegedAction() {
            public Object run() {
                return System.getProperty("user.name");
            }
          }
        );
        ...normal code here...
  }

Gruß,
Fancy
 

benhaze

Mitglied
AccessController.doPrivileged hat nichts gebracht, da letztendlich alles im Security-Context der Webstart-anwendung läuft.

Bisher habe ich es so gelöst:

Beim Starten der Anwendung prüfe ich, ob diese via Webstart gestartet wurde.
Wenn dem so ist, hole ich mir die geladen JARs von der Webstart-Anwendung und
erstelle mittels ProcessBuilder einen neuen Java-Prozess der Anwendung.
Der Webstart-Prozess beendet automatisch.

- es ist keine spürbare Verzögerung zu bemerken.
- die JARs sind aufgrund des Webstart-Mechanismus immer aktuell
 

Ähnliche Java Themen


Oben