Java plug-in : alert dialog for signed applet NOT waiting user answer
Hi!
I am running a signed applet.
EXPECTED BEHAVIOUR :
====================
1) BEFORE the applets loads, a message prompt for whether trust the certificate that signed the applet
2) the user click YES, NO , or ALWAYS
3) the applet is loaded by the browser either with or without secured access enabled (init and then start).
NOTICED BEAHIVOUR:
===================
1) i get the alert message (trus certificate or not), but the applet is loaded simultaneously
==> either i was fast enough to click YES and the applet has the secured access
==> or i was too slow and the applet does not have the access, even though i clicked YES ...
With plug-in 1.4.1_01, i do not have any problem.
With 1.4.2_02, i get the bug with :
-- netscape 6/7
-- IE 6 (i bet IE5 too)
-- NOT with opera 7 (expected behaviour)
Is this really a bug ?
Furthermore, i tried a brutal workaround :
"while i do not have the permission
get the appletContext
check whether i have the permission
" ==> i never get the permission...
Anyone noticed the same bug ?
Do you have a workaround for this ?
Is this really a bug as i think ?
I hope this will be corrected in later versions, because i would be ashamed to tell people to DOWNGRADE their JVM :)
Thanx in advance for any help.
Regards,
Jelloul.
[1460 byte] By [
diesmoa] at [2007-9-29 22:20:17]

Ok things are a little bit clearer.
In fact the problem is different.
You use an unsigned applet which makes a redirection to a page using a signed applet, using :
getAppletContext().showDocument(new URL(thePage));
WHAT FOR ? Typically, you may use this when an applet somewhere in your application relies on a library which is not installed by default ( Apache XERCES for example).
Sometimes the library is very big (2Mo for XERCES ?), so you prefer to install it once on the disk, instead of including in the applet that uses the library.
To do this, you simply sign the JAR file containing the library and copy it to the $JAVA_HOME/lib/ext of the user's disk.
So you use an applet that verifies (with a Class.forName(someClassOfTheLibrary) ) the existence of the library, and redirects if needed to a page that copies the library to the disk.
The problem is that when switching from the Unsigned applet's page to the Signed applet's page, the plug-in does not wait for the user to grant privileges to the signed applet : the applet is loaded in the sandbox.
It seems that the Context of the first applet is reused/cloned for the second applet ?
A simple workaround is to sign the applet that checks the existence of the library ==> everything OK after that (though it is stupid to sign an applet just for fun...)
I tried to modify the call to the showDocument() method by adding "_top", "_self", "_parent" or "_blank".
When using _blank, it works, the new page wait for the user to click YES or NO.
The other choices do not work.
I tried to list the applets used in the AppletContext in both pages, and to get the reference of the context in both pages, but they are different...
===> The context is cloned ?
To me, this CANNOT be a totally expected behaviour of the plug-in, something is wrong...
Regards.
[nobr]Here is sample code.
The problem occurs when using Threads (and is not systematic). i tried it on mozilla 1.5 and internet explorer 6, with jre 1.4.2_03.. Applets are signed using signtool.
The workaround i found works, so i do not need any answer ...
The simplified code uses Threads because the original applet uses graphics, popups, etc.
I put all the jars and web pages on a sever in /test directory.
Regards.
=================================================================================
PAGE CONTAINING THE UNSIGNED APPLET:
=================================================================================
unsecureapplet.html
================
<html>
<head>
<title>Unsecure applet Test</title>
</head>
<body>
Please wait....<br>
<!-- in the original code, This applet checks for the library-->
<applet name='unsecureApplet'
code='SimpleUnsecureApplet.class'
codebase='http://172.20.8.3/test'
archive='unsecureapplet.jar'
width='700' height='100'MAYSCRIPT>
</applet>
<!-- In the original code, This applet needs the library to run correctly-->
<applet name='secureApplet2'
code='SimpleSecureApplet2.class'
codebase='http://172.20.8.3/test'
archive='secureapplet2.jar'
width='700' height='100'MAYSCRIPT>
</applet>
<!-- Ok; a better way of coding would be to put the second applet in a different page, and make the "check" applet redirect either
to the installation page, or to the page with SimpleSecureApplet2 :) -->
</body>
</html>
==================================================================================
PAGE CONTAINING THE SIGNED APPLET:
==================================================================================
secureapplet.html
==================================================================================
<html>
<head>
<title>Secure applet Test</title>
</head>
<body>
Here is a simple test of a signed applet that tries to read the java.home property.<br>
<!-- in the original code, this applet installs the library on the disk-->
<applet name='secureApplet'
code='SimpleSecureApplet.class'
codebase='http://172.20.8.3/test'
archive='secureapplet.jar'
width='700' height='100'MAYSCRIPT>
</applet>
</body>
</html>
==================================================================================
UNSIGNED APPLET 1:
==================
/**
*
* SimpleUnsecureApplet.java
*
*/
import java.awt.event.*;
import java.applet.*;
import java.security.*;
import java.net.*;
public class SimpleUnsecureApplet extends Applet implements Runnable, ActionListener {
public void start(){
new Thread(this).start();
}
static {
System.err.println("SimpleUnsecureApplet Executing the static methods");
}
public void run() {
System.err.println("SimpleUnsecureApplet Executing the run method");
System.err.println("SimpleUnsecureApplet Redirecting the client...");
try {
getAppletContext().showDocument(new URL("http://172.20.8.3/test/secureapplet.html"));
} catch(Exception e){
System.err.println("SimpleUnsecureApplet Exception occurs !");
e.printStackTrace();
// GC
e = null;
}
}
public void init() {
System.err.println("SimpleUnsecureApplet Executing the init method");
}
public void actionPerformed(ActionEvent e) {
}
}
==================================================================================
SIGNED APPLET 1:
===============
/**
*
* SimpleSecureApplet.java
*
*/
import java.applet.*;
import java.security.*;
public class SimpleSecureApplet extends Applet implements Runnable{
private boolean checkSecureAccess(){
AccessControlContext acc = null;
try {
// get the applet context
acc = AccessController.getContext();
// do privileged stuff
String javaHome = (String) AccessController.doPrivileged(new PrivilegedAction() {
public Object run() {
return System.getProperty("java.home");
}
}, acc);
System.out.println("SimpleSecureApplet Found java home = "+javaHome);
// GC
acc = null;
} catch(Exception e){
System.err.println("SimpleSecureApplet Exception occurs !");
e.printStackTrace();
// GC
e = null;
acc = null;
// EXIT FAILURE
return false;
}
// EXIT SUCCESS
return true;
}
static {
System.err.println("SimpleSecureApplet Executing the static methods");
}
public void run() {
System.err.println("SimpleSecureApplet Executing the run method");
System.out.println( "SimpleSecureApplet Result : "+checkSecureAccess());
}
public void init() {
System.err.println("SimpleSecureApplet Executing the init method");
}
public void start(){
System.err.println("SimpleSecureApplet Executing the start method");
new Thread(this).start(); // <==== problem does not occur when NOT using threads
}
}
==============================================================================
SIGNED APPLET 2
===============
/**
*SimpleSecureApplet2.java
*
*/
import java.applet.*;
import java.security.*;
public class SimpleSecureApplet2 extends Applet implements Runnable {
private boolean checkSecureAccess(){
AccessControlContext acc = null;
try {
// get the applet context
acc = AccessController.getContext();
// do privileged stuff
String javaHome = (String) AccessController.doPrivileged(new PrivilegedAction() {
public Object run() {
return System.getProperty("java.home");
}
}, acc);
System.out.println("SimpleSecureApplet2 Found java home = "+javaHome);
// GC
acc = null;
} catch(Exception e){
System.err.println("SimpleSecureApplet2 Exception occurs !");
e.printStackTrace();
// GC
e = null;
acc = null;
// EXIT FAILURE
return false;
}
// EXIT SUCCESS
return true;
}
static {
System.err.println("SimpleSecureApplet2 Executing the static methods");
}
public void run() {
System.err.println("SimpleSecureApplet2 Executing the run method");
System.out.println( "SimpleSecureApplet2 Result : "+checkSecureAccess());
}
public void init() {
System.err.println("SimpleSecureApplet2 Executing the init method");
}
public void start(){
System.err.println("SimpleSecureApplet2 Executing the start method");
new Thread(this).start();
}
}
===============================================================================[/nobr]