创建访问本地文件系统的信任APPLET
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())); } } }<html><body><applet code="SignedApplet.class" archive="SignedApplet.jar" width=325 height=325> </applet> </body></html>