Written By Olexiy & Alexander Prokhorenko
Translated by Caiyi0903(Willpower),2004.1.29
创建一个信任的APPLET,使其拥有本地客户端文件系统的访问权限,这一直是一个重要的话题。依赖于一些规范,许多问题仅仅只能在客户端被执行。因此,很多情况下,不熟悉信任APPLET技术的程序员们大都认为不可能实现对客户端文件的操作和搜索其他的操作方式。然而,确实存在这样一种方式,且可以在很多方面被广泛使用。在本文中,我将给你展示一个范例,来创建简单的信任APPLET,它将访问一个你指定的本地文本文件(注意:你需要使用JDK1.3或者更高的版本)。
首先,我要谈一下我们不得不在客户端软件上所做的限制。我要声明一下,本文给定的签名APPLET仅仅只适合于安装有JDK(1.3版本以上)或类似插件的客户机,且使用IE 4以上或Netscape 4.75以上版本的浏览器。除这些条件以外的客户机,将不支持本文的要求,为这些老式的其他客户机创建信任的签名APPLET需要JDK1.1技术,使用的是javakey工具。因为采用老的方式创建签名APPLET已经超过了本文所描叙的范围,所以有必要在这里解释一下。
现在,再来说说我们(程序员)的平台。我们使用的是Windows平台,安装有J2SDK 1.4.1和JAVA容器Jakarta-Tomcat 4.1.29。如果你使用的是相同的软件,那么可以100%的保证本文描叙的所有内容都将完美的在你的平台下运行。一般而言,本文描叙的所有内容应该能在兼容的软件上运行。
开始编码之前,我要解释一下为什么我们需要找出一种特定的而不是没有价值的方式来做这些简单的标准的事情,比如读本地文件等。在JAVA 1.1时代存在一种观点,认为有必要在APPLET的帮助下将一部分要执行的任务转移到客户端计算机上,来创造未来的一代网络计算机。然而,由于APPLET限制了安全性,所以这种做法不可能实现。开发者们也推测出了APPLET是一种所谓的“沙盒”(sandbox)----一个简单的位置----不允许引用任何系统函数。随着JAVA技术的发展,信任的APPLET(trusted Applet)被发明出来,在这种APPLET中的“沙盒”安全规则不被包含在内。那么我们应该怎么利用这个机会呢?下面我们将找到答案。
在JDK中,除了javac,我们还需要两个额外的实用工具--keytool和jarsigner。keytool是一个用来创建和控制一对私有和公共密匙的工具,用来管理你的私有密匙,即.keystore文件。jarsigner工具是用来给一个jar文件签名,该jar文件里有一个APPLET类,它可以用来验证和APPLET一起分发的数字签名。签名的整个过程非常的简单;然而,我们需要做一些初始化的准备工作。首先让我们来创建我们的APPLET。其中有一个文本域(text field),我们会在那里输入一个文件名,一个大的文本区域(text area)用来显示文件内容,一个LOAD按钮将执行文件读取工作。这个APPLET的源代码如下图所示,因为它很简单,我们给它加入了一些注释。我们没有特别的给它添加一些特殊的检查框和更复杂的功能,所以该代码很容易阅读,而且读者能够集中关注它转变到信任APPLET的过程。除此之外,你甚至也能够根据你自己的喜欢的可视化工具(如SUN ONE Studio,JBUILDER等)来创建你自己的APPLET,但我们提供的这个源代码能帮助你更快的理解APPLET签名的整个过程。
// TestApplet.java import java.io.*; import java.awt.*; import java.awt.event.*; import java.applet.*; import javax.swing.*; import javax.swing.border.*; public class TestApplet extends JApplet implements ActionListener { private JPanel pane = null; private JScrollPane scrolling = null; private JTextPane fileBox = null; private JTextField tfFilename = null; private JButton butLoad = null; private final String LOAD = "load"; public void init() { try { jbInit(); } catch(Exception e) { e.printStackTrace(); } } // method which will read data from file, and return it in // String public String readFile(String fn) { String thisLine, ret = ""; try { FileInputStream fin = new FileInputStream(fn); BufferedReader myInput = new BufferedReader (new InputStreamReader(fin)); while ((thisLine = myInput.readLine()) != null) { ret += thisLine + "/n"; } } catch (Exception e) { ret = "Cannot load, exception!"; } return ret; } private void jbInit() throws Exception { pane = new JPanel(); pane.setBounds(new Rectangle(0, 0, 500, 325)); pane.setLayout(null); pane.setBorder(BorderFactory.createEtchedBorder( EtchedBorder.LOWERED)); pane.setBackground(new Color(221, 194, 219)); fileBox = new JTextPane(); fileBox.setText(""); fileBox.setEditable(false); scrolling = new JScrollPane(fileBox); scrolling.setBounds(new Rectangle(16, 65, 295, 225)); tfFilename = new JTextField(); tfFilename.setText(""); tfFilename.setBounds(new Rectangle(16, 23, 206, 29)); butLoad = new JButton(); butLoad.setBounds(new Rectangle(231, 23, 80, 30)); butLoad.setText("Load"); butLoad.setActionCommand(LOAD); butLoad.addActionListener(this); pane.add(scrolling); pane.add(tfFilename); pane.add(butLoad); setContentPane(pane); } public void actionPerformed(ActionEvent e) { if (e.getActionCommand().equals(LOAD)) { fileBox.setText(readFile(tfFilename.getText())); } } }
下面的步骤也很简单。我们要编译,创建一个JAR压缩包,创建一个简单的HTML文件来演示文本文件并试图使用它。也许它还能够加载一个文件而不使用签名技术。让我们来看看,要编译和创建一个JAR压缩包,采用下面的步骤:
javac TestApplet.java
jar cvf TestApplet.jar TestApplet.class
这里的cvf参数是指定JAR包的文件名为TestApplet.jar,并显示详细的输出信息。
好了,让我们接下来用任一种文本编辑器来创建TestApplet.html 文件。
<html><body> <applet code="SignedApplet.class" archive="SignedApplet.jar" width=325 height=325> </applet> </body></html>
然后在同一个文本编辑器中随便创建一个文本文件,比如 C:/Demo.txt,在这个文件中,你需要输入一些单词和句子。在这里,我们输入HelloWorld。因此,如果它被成功加载,你应该能够看见这些内容。
拷贝你的TestApplet.html和TestApplet.jar 文件到你的TOMCAT的WEBAPP目录中,该目录存放着你的Web应用程序。然后浏览这个HTML文件,在这里是http://localhost:8080/green/TestApplet.html
当APPLET被加载,输入文本文件路径(C:/Demo.txt)并点击“Load”按钮。下面将是你所看到的:
OK,我们得到一个异常信息。这个不算惊奇。让我们来尝试给它签名,再看看有什么事情发生了改变。你要采用下列方式运行toolkey工具:
keytool -genkey -alias TestApplet -validity 365
这条语句将产生一个别名为TestApplet的密匙证书(key certificate),该证书将存储在你的.keystore文件中。Validity指的是密匙的有效期,默认是180,但是这里我们需要一年的时间,所以我们设置为365。在Windows命令提示行窗口中运行这条语句,你会从keytool中得到大量需要回答的简短问题,如下图所示:
可能你已经理解到了,最重要的东西当然是密码。你可以使用你自己的密码,但是不要忘记它。我前面说过,创建信任APPLET是一个很简单的操作,但是你要理解每一步的道理。这里,我们几乎已经完成了它的操作,但还是要针对keytool说几句。我建议你多多注意它,阅读keytool的手册来了解每个参数的用法是有必要的,对于你深入理解它的特性是很有帮助的。好了,既然我们产生了我们自己的密匙,让我们来做个简单操作吧:仅仅用我们的密匙来设计我们的APPLET。使用下面的命令行(请改变当前目录到TestApplet.jar存放的目录):
jarsigner TestApplet.jar TestApplet
第一个参数是我们的jar文件,第二个是上面刚刚创建的密匙别名(Key Alias)。jarsigner命令不是友好的,因此你将看不到任何信息。
恭喜,你已经成功创建了你的第一个真正的签名APPLET!我想你恨不得马上尝试一下它的功能吧,我也找不出任何理由不让你这么做。上传或者仅仅拷贝你签名的JAR文件到放置你先前的TestApplet.html和TestApplet.jar的那个目录中,然后覆盖TestApplet.jar文件。在浏览器中浏览TestApplet.html。
然后你的Applet会加载,并显示一个窗口,如下所示:
它询问你是否接受或者拒绝这个签名的APPLET。点击“No”将以旧的未签名的版本来显示APPLET,那样它仍然位于“沙盒”中且对“外面的世界”有很多约束。点击“Yes”将以你的APPLET获得更多的自由。
这里,我们点击“Yes”,我们的APPLET被打开。现在,我要做上面同样的操作:输入我们本地文件(c:/Demo.txt)的路径,点击“Load”按钮:
我相信你也得到了同样的结果。我们的任务完成了。所有问题都不是很难,也不是很复杂。你仅仅要理解每一步为什么要那么做的道理。如果你对此主题感兴趣,请浏览http://java.sun.com/j2se/1.3/docs/tooldocs/win32/jarsigner.html以获取更多官方信息。