Authentication 提供了关于认证发起者的足够多的信息让继承类根据这些信息进行判断在 getPasswordAuthentication 方法中给出了不同的认证信息
getRequestingHost() getRequestingPort() getRequestingPrompt() getRequestingProtocol() getRequestingScheme() getRequestingURL() getRequestingSite() getRequestorType()
另一件关于 Authentication 的重要问题是认证类型不同的认证类型需要 Authentication 执行不同的协议至 Java SE 为止Authentication 支持的认证方式有
HTTP Basic authentication HTTP Digest authentication NTLM Http SPNEGO Negotiate Kerberos NTLM
这里我们着重介绍 NTLM
NTLM 是 NT LAN Manager 的缩写早期的 SMB 协议在网络上明文传输口令这是很不安全的微软随后提出了 WindowsNT 挑战/响应验证机制即 NTLM
NTLM 协议是这样的
·客户端首先将用户的密码加密成为密码散列
·客户端向服务器发送自己的用户名这个用户名是用明文直接传输的
·服务器产生一个 位的随机数字发送给客户端作为一个 challenge(挑战)
·客户端用步骤得到的密码散列来加密这个 challenge 然后把这个返回给服务器
·服务器把用户名给客户端的 challenge 客户端返回的 response 这三个东西发送域控制器
·域控制器用这个用户名在 SAM 密码管理库中找到这个用户的密码散列然后使用这个密码散列来加密 challenge
·域控制器比较两次加密的 challenge 如果一样那么认证成功
Java 以前的版本是不支持 NTLM 认证的用户若想使用 HttpConnection 连接到一个使用有 Windows 域保护的网站时是无法通过 NTLM 认证的另一种方法是用户自己用 Socket 这样的底层单元实现整个协议过程这无疑是十分复杂的
终于Java 的 Authentication 类提供了对 NTLM 的支持使用十分方便就像其他的认证协议一样
class DefaultAuthenticator extends Authenticator {private static String username = username ;private static String domain = domain ;private static String password = password ;public PasswordAuthentication getPasswordAuthentication() {String usernamewithdomain = domain + / +username;return (new PasswordAuthentication(usernamewithdomain password
toCharArray()));}}
这里根据 Windows 域账户的命名规范账户名为域名+/+域用户名如果不想每生成 PasswordAuthentication 时每次添加域名可以设定一个系统变量名
Java 中 Authentication 的另一个特性是认证协商目前的服务器一般同时提供几种认证协议根据客户端的不同能力协商出一种认证方式比如IIS 服务器会同时提供 NTLM with kerberos 和 NTLM 两种认证方式当客户端不支持 NTLM with kerberos 时执行 NTLM 认证
目前Authentication 的默认协商次序是
GSS/SPNEGO > Digest > NTLM > Basic
那么 kerberos 的位置究竟在哪里呢?
事实上GSS/SPNEGO 以 JAAS 为基石而后者实际上就是使用 kerberos 的
轻量级 HTTP 服务器
Java 还提供了一个轻量级的纯 Java Http 服务器的实现下面是一个简单的例子
public static void main(String[] args) throws Exception{HttpServerProvider ();InetSocketAddress addr = new InetSocketAddress();HttpServer httpServer = (addr );(/myapp/ new MyHttpHandler());(null);();Systemoutprintln(started);}static class MyHttpHandler implements HttpHandler{public void handle(HttpExchange httpExchange) throws IOException { String response = Hello world!;( responselength());OutputStream out = ();outwrite(responsegetBytes());outclose();} }