摘要
Java SE 有着很多 HTTP 相关的新特性使得 Java SE 平台本身对网络编程尤其是基于 HTTP 协议的因特网编程有了更加强大的支持
概述
Java 语言从诞生的那天起就非常注重网络编程方面的应用随着互联网应用的飞速发展Java 的基础类库也不断地对网络相关的 API 进行加强和扩展在 Java SE 当中围绕着 HTTP 协议出现了很多实用的新特性NTLM 认证提供了一种 Window 平台下较为安全的认证机制JDK 当中提供了一个轻量级的 HTTP 服务器提供了较为完善的 HTTP Cookie 管理功能更为实用的 NetworkInterfaceDNS 域名的国际化支持等等
NTLM 认证
不可避免网络中有很多资源是被安全域保护起来的访问这些资源需要对用户的身份进行认证下面是一个简单的例子
import *;import javaio*;public class Test {public static void main(String[] args) throws Exception {URL url = new URL();URLConnection connection = urlopenConnection();InputStream in = connectiongetInputStream();byte[] data = new byte[];while(inread(data)>){//do something for data}inclose();}}
当 Java 程序试图从一个要求认证的网站读取信息的时候也就是说从联系于 这个 URLConnection 的 InputStream 中 read 数据时会引发 FileNotFoundException尽管笔者认为这个 Exception 的类型与实际错误发生的原因实在是相去甚远但这个错误确实是由网络认证失败所导致的
要解决这个问题有两种方法
其一是给 URLConnection 设定一个Authentication属性
String credit = USERNAME + : + PASSWORD;String encoding = new sunmiscBASEEncoder()encode (creditgetBytes());connectionsetRequestProperty (Authorization Basic + encoding);
这里假设 使用了基本(Basic)认证类型
从上面的例子我们可以看出设定 Authentication 属性还是比较复杂的用户必须了解认证方式的细节才能将用户名/密码以一定的规范给出然后用特定的编码方式加以编码Java 类库有没有提供一个封装了认证细节只需要给出用户名/密码的工具呢?
这就是我们要介绍的另一种方法使用 Authentication 类
每当遇到网站需要认证的时候HttpURLConnection 都会向 Authentication 类询问用户名和密码
Authentication 类不会知道究竟用户应该使用哪个 username/password 那么用户如何向 Authentication 类提供自己的用户名和密码呢?
提供一个继承于 Authentication 的类实现 getPasswordAuthentication 方法在 PasswordAuthentication 中给出用户名和密码
class DefaultAuthenticator extends Authenticator {public PasswordAuthentication getPasswordAuthentication () {return new PasswordAuthentication (USER PASSWORDtoCharArray());}}
然后将它设为默认的(全局)Authentication
AuthenticatorsetDefault (new DefaultAuthenticator());
那么不同的网站需要不同的用户名/密码又怎么办呢?