从浏览器访问一个诸如 http://www.lombard.com/cgi-bin/Quotes/quote 这样的 URL 不成问题,因为您自己可以提供用户名和口令。但是当您试图通过 Java 程序从与此 URL 相关的 InputStream
中读取数据时,该 Java 程序就会发出 FileNotFoundException
异常。
在 Java 1.0 或 1.1 中,您可以通过在连接时记入 (post) 适当的认证字符串来避免这种情况,但这种方法仅在您事先知道该 URL 是受保护的时才奏效。(Authorization: Basic username:password
,其中基本认证域是以 base 64 编码的。)如果您事先没有预见到文档是受保护的,则您甚至无法读取文件内容。(有关用 Java 1.1 applet 或应用程序访问口令保护的 URL 的解决方案,请参阅“tips/tip047/index.shtml">Java 技巧 47:再谈 URL 认证”。值得庆幸的是,Java 1.2 在 java.NET
包中添加了一个 Authenticator
类,这使得访问口令保护的 URL 变得极为容易。
现在,对于 Java 1.2,您只需用 Authenticator.setDefault()
安装一个 Authenticator
。这样,当需要认证时,已安装的 Authenticator
的 getPasswordAuthentication()
方法就会被调用,然后您就可以用适当的用户名和口令来设置 PasswordAuthentication
实例。就这么简单。
所需步骤如下所示。
第一步:安装 Authenticator
Authenticator.setDefault (new MyAuthenticator ());
第二步:创建 Authenticator 的子类
class MyAuthenticator extends Authenticator {
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication ("username", "password");
}
}
以下程序完整地显示了这种行为,它提供了自己的认证提示对话框。
import java.io.*;
import java.net.*;
import java.awt.*;
import java.awt.event.*;
public class URLPassword extends Frame {
private TextField tf = new TextField();
private TextArea ta = new TextArea();
public URLPassword() {
super ("URL Password");
// 安装 Authenticator
Authenticator.setDefault (new MyAuthenticator ());
// 设置屏幕
add (tf, BorderLayout.NORTH);
ta.setEditable(false);
add (ta, BorderLayout.CENTER);
tf.addActionListener (new ActionListener() {
public void actionPerformed (ActionEvent e) {
String s = tf.getText();
if (s.length() != 0)
ta.setText (fetchURL (s));
}
});
addWindowListener (new WindowAdapter() {
public void windowClosing (WindowEvent e) {
dispose();
System.exit(0);
}
});
}
private String fetchURL (String urlString) {
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
try {
URL url = new URL (urlString);
InputStream content = (InputStream)url.getContent();
BufferedReader in =
new BufferedReader (new InputStreamReader (content));
String line;
while ((line = in.readLine()) != null) {
pw.println (line);
}
} catch (MalformedURLException e) {
pw.println ("Invalid URL");
} catch (IOException e) {
pw.println ("Error reading URL");
}
return sw.toString();
}
public static void main (String args[]) {
Frame f = new URLPassword();
f.setSize(300, 300);
f.setVisible (true);
}
class MyAuthenticator extends Authenticator {
protected PasswordAuthentication getPasswordAuthentication() {
final Dialog jd = new Dialog (URLPassword.this, "Enter password", true);
jd.setLayout (new GridLayout (0, 1));
Label jl = new Label (getRequestingPrompt());
jd.add (jl);
TextField username = new TextField();
username.setBackground (Color.lightGray);
jd.add (username);
TextField password = new TextField();
password.setEchoChar ('*');
password.setBackground (Color.lightGray);
jd.add (password);
Button jb = new Button ("OK");
jd.add (jb);
jb.addActionListener (new ActionListener() {
public void actionPerformed (ActionEvent e) {
jd.dispose();
}
});
jd.pack();
jd.setVisible(true);
return new PasswordAuthentication (username.getText(), password.getText());
}
}
}
后续技巧! 来自 Luis Blanco Gomez
代码的第 85 行(MyAuthenticator
类的返回参数)显示一个错误:
return new PasswordAuthentication (username.getText(), password.getText());
编译器将报错:
URLPass.java:88: Incompatible type for constructor. Can't convert
java.lang.String to char[].
return new PasswordAuthentication ( username.getText(), password.getText());
为修正此错误,您必须声明一个 String 变量来存储 password.getText()
;例如,"String pass= password.getText();",并将返回行改为:
return new PasswordAuthentication ( username.getText(), pass.toCharArray());
有几点值得一提:不可信的 applet 可在 appletviewer 中安装一个缺省的 Authenticator
。HotJava、Navigator 和 Internet Explorer 会怎么做尚不清楚。如果您没有必要的权限便试图更改 authenticator,该程序就会发出一个 AccessControlException
异常。
提交您喜好的 Java 技巧
每篇技巧都将提供有关有用的技巧和窍门的几则简短信息,以帮助您改进 Java 代码。我们将探究这一出色技术的诸多方面,每次讨论一个 Java bean。
我们也希望将您的 Java 技巧刊登在以后的 Java world 上。赶快将您最棒的技巧和窍门写出来并发送到 Mailto.cgi?javatips@javaworld.com+/javaworld/javatips/jw-javatips.index.html+javatip" name=javatip>javatips@javaworld.com。您可能会发现自己成了 JavaWorld 的一名作者,因为您的有益提示可能成为下一篇 Java 技巧!
作者简介
john.zukowski John Zukowski 是 MageLang Institute 的一位软件专家,他是 Java AWTReference(O'Reilly& Associates 出版)、Borland's JBuilder: No experience required(Sybex 出版)两本书的作者,同时也是 Mining Company 的 Focus on Java 指南的作者。