安全性是当前程序设计工作中的一个重要方面由于应用程序在网络上呈分散分布因而每个部分都需要保护自己的基础框架部分而这在以前是内置到主应用程序中的随着这些情况的变化作为基础的 JavaTM 平台发行版也进行了不断演变并在 JSE 发行版 中并入了越来越多的功能从而提供了一个可以执行移动代码的安全环境
在最新的 发行版中您会发现在安全体系结构中实现了许多增强功能以前单独提供的几个功能现已成为核心 API 集中的一部分其中包括通过 Java Cryptography Extension (JCE) 支持加密和解密通过 Java Secure Socket Extension (JSSE) 实现的对安全套接字层 (SSL) 和传输层安全性 (TLS) 协议的支持以及通过使用 Java Authentication and Authorization Service (JAAS) 实现的对基于用户的身份鑒定和访问控制的支持除了包含这些以前的可选软件包以外您还会发现新增了通过使用 Java Certification Path API实现的对生成和检验证书链的支持以及对 Java GSSAPI 和 JAAS 下的 Kerberos V 机制的支持此外还改进了安全策略管理工具 policytool并添加了对动态载入安全策略的支持
以下各节将介绍并深入检查所有这些功能
Java Cryptography Extension
在 Java Cryptography Extension (JCE) 库中您会发现对加密解密密钥协议信息鑒定代码 (MAC)以及其它加密法服务的支持由于某些国家/地区的进口控制限制Java SDK 发行版附带的JCE 辖区政策文件允许使用强大但有限的加密法而在其它国家/地区(占大多数)则可以使用这些文件的完全版本从而充分利用其强大的加密法而不受任何限制您可以下载此版本并使用此不受限制的版本替换随 Java SDK 发行版提供的字符串加密法版本
JCE 库可以将无格式文本转换为密文或反向转换在 javaxcrypto 软件包中可以找到该库这里的密钥类是 Cipher它决定了用于加密和解密的加密算法借助 CipherOutputStream 和 CipherInputStream 类所提供的方便这些 I/O 过滤流可以完成加密或解密任务当您向流中写入或从中读取时适当的流便传递给了构造函数然后它们便可以完成各自的任务您唯一需要关心的是密钥的管理和使用什么样的 Cipher 算法
为演示 JCE API以下程序将对一系列对象进行加密然后再解密该示例使用数据加密标准 (DES) 作为加密算法有关所支持的算法的完整列表请参阅 Java Cryptography Extension (JCE) Reference Guide
代码样例 通过加密和解密一系列对象演示 JCE API
import javaio*;
import javaxcrypto*;
import javaxcryptospec*;
import javasecurity*;
import javasecurityspec*;
import javautil*;
public class EncryptTest {
public static void main(String args[]) {
File desFile = new File(outdes);
// 创建要加密的数据
Map map = new TreeMap(SystemgetProperties());
int number = mapsize();
try {
// 创建密钥
KeyGenerator kg = KeyGeneratorgetInstance(DES);
SecretKey secretKey = kggenerateKey();
// 创建密码
Cipher desCipher =
CiphergetInstance(DES/ECB/PKCSPadding);
desCipherinit(CipherENCRYPT_MODE secretKey);
// 创建流
FileOutputStream fos = new FileOutputStream(desFile);
BufferedOutputStream bos = new BufferedOutputStream(fos);
CipherOutputStream cos = new CipherOutputStream(bos
desCipher);
ObjectOutputStream oos = new ObjectOutputStream(cos);
// 写对象
ooswriteObject(map);
ooswriteInt(number);
oosflush();
oosclose();
// 更改密码模式
desCipherinit(CipherDECRYPT_MODE secretKey);
// 创建流
FileInputStream fis = new FileInputStream(desFile);
BufferedInputStream bis = new BufferedInputStream(fis);
CipherInputStream cis = new CipherInputStream(bis
desCipher);
ObjectInputStream ois = new ObjectInputStream(cis);
// 读对象
Map map = (Map)oisreadObject();
int number = oisreadInt();
oisclose();
// 将读回的内容与原始内容相比较
if (mapequals(map) && (mapsize() == number)) {
Systemoutprintln(Everything read back out okay);
} else {
Systemoutprintln(Problems during
encryption/decryption process);
}
} catch (NoSuchPaddingException e) {
Systemerrprintln(Padding problem: + e);
} catch (NoSuchAlgorithmException e) {
Systemerrprintln(Invalid algorithm: + e);
} catch (InvalidKeyException e) {
Systemerrprintln(Invalid key: + e);
} catch (IOException e) {
Systemerrprintln(I/O Problem: + e);
} catch (ClassNotFoundException e) {
Systemerrprintln(Class loading Problem: + e);
} finally {
if (desFileexists()) {
desFiledelete();
}
}
}
}
Java Secure Socket Extension
接下来将介绍 Java Secure Socket Extension (JSSE) 库从中您会发现对使用安全套接字层 (SSL) 和传输层安全性 (TLS) 协议进行通信的支持与对特定的本地数据结构执行操作的 JCE 不同JSEE 使用了另一种提取方法从而对网络套接字通信应用加密/解密技术它添加了服务器鑒定信息完整性和可选的客户机鑒定大多数人把 SSL 和 TLS 视为安全的 HTTP 协议并称为 HTTPS
JSSE 库位于 和 ssl 软件包中要使用 SSL 进行套接字通信您必须借助一个辅助机制 而不是从其构造函数中创建 Socket首先从 SSLSocketFactory 获取一个 SocketFactory然后再从该工厂创建 Socket当建立了安全连接后只需写入套接字或从中读取即可对数据进行加密或解密在此机制之上可以建立其它高层协议如 HTTPS
SSL(亦即 HTTPS)允许在客户机和服务器之间交换加密的通信当 SSL 客户机开始与 SSL 服务器的对话后服务器会向客户机发送回一个 X 证书要求进行鑒定然后客户机将检查该证书的有效性假设服务器通过检验客户机将预先生成一个安全密钥然后使用证书中的服务器的公共密钥对其进行加密并将加密后的密钥发送回服务器根据此事先掌握的密钥客户机和服务器将为会话生成一个主密钥经过一番基本的握手程序后加密交换便可以开始了
JSSE 库对您隐藏了 SSL 协议的这些内部工作您只需象对待普通套接字一样使用从工厂创建的 Socket
以下示例演示了如何使用 JSSE 库它使用 SSL 读取了一个 Web 页即使发送到服务器的 GET 命令说明要使用 HTTP协议但因为 Socket 是从 SSLSocketFactory 创建的所以仍然使用了 SSL 与服务器进行通信以发送页面请求并接收响应
代码样例 通过从端口 (即 HTTPS 端口)读取 Web 页演示如何使用 JSSE 库
import javaio*;
import *;
import *;
import ssl*;
public class JSSE {
static final int HTTPS_PORT = ;
public static void main(String args[]) {
String hostname;
// 获得主机名或使用 VeriSign
if (argslength == ) {
hostname = ;
} else {
hostname = args[];
}
try {
// 获得套接字工厂
SocketFactory factory = SSLSocketFactorygetDefault();
// 从工厂获得套接字
Socket s = factorycreateSocket(hostname HTTPS_PORT);
// 发送请求
OutputStream os = sgetOutputStream();
PrintWriter pw = new PrintWriter(os);
// 设置命令
String command = GET / HTTP/\r\n\r\n;
pwprint(command);
pwflush();
// 获得响应
InputStream is = sgetInputStream();
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
String line;
while ((line = brreadLine()) != null) {
Systemoutprintln(line);
}
pwclose();
brclose();
sclose();
} catch (IOException e) {
Systemerrprintln(Error reading: + e);
}
}
}
在创建服务器而不是客户机的情况下您会从 SSLServerSocketFactory 获得一个 ServerSocket
还请注意JSE 发行版中的 JSSE 库与 JSSE 发行版中的 JSSE 库不同例如ssl 软件包现在是 ssl 软件包并且新增和修改了某些接口和类在 Sun 的 JSE 发行版中Wrapper