天天看点

Java安全——提供者相关的体系架构

标签(空格分隔): Java 安全

[toc]

Java的安全软件特性,是通过安全软件包的概念透出的。换句话说,安全领域常见的鉴别、加密、签名等概念,在Java中的支持是通过安全软件包来实现的。Java对于安全软件包的定义其实是一组抽象接口。Sun作为Java的作者,提供了一组实现。而安全软件包是由安全提供者、算法和引擎组成的。引擎可以理解为一组操作,算法定义了操作如何执行,而安全提供者则负责实现这两个抽象概念。

比如说,消息摘要是一个引擎,它是程序员能执行的一个操作。消息摘要的思想与如何计算消息摘要没有关系,所有的消息摘要具备同样的特性,因此抽象出来的接口就是引擎。而实现消息摘要可以有MD5和SHA等算法,算法由具体类实现。而安全提供者就是二者的桥梁,用来管理引擎和算法。安全提供者的目的就是提供一个简单的机制,从而可以方便的改变或替换算法及其实现。因此,通过安全提供者,程序员只需要使用引擎的接口,而不需要关系具体哪个类实现了算法,算法由哪个安全提供者提供。

Java安全软件包的体系结构可以总结为四个部分:

JVM提供引擎类,是Java核心API的一部分。

针对每一种引擎,都会有一组算法实现。Java提供了一组默认的算法实现(由Sun提供),第三方的机构可以提供其他实现。

算法类是由提供者来管理的,提供者知道如何将算法与实现的具体类对应起来。

安全类保存提供者列表,可以通过安全类查看有哪些提供者,以及它们提供的算法支持有哪些。

安全提供者体系的一个流程如下:

以MessageDigest的getInstance()方法为例,发现其实是调用Security.getImpl()方法实现的,而内部又是通过

这样的语句来做的。而这个GetInstance会返回一个Instance对象,其类声明如下:

可见就是一个Provider和Object(具体算法)的封装。

JVM在启动时,会去$JREHOME/lib/security/java.security中注册提供者。以我个人电脑中的文件为例:

JVM启动时会将这些provider注册进去,其实就是Security

初始化时会读这个文件。开发自定义的安全提供者,需要将类放到系统类路径下。其实看看Provider类的代码,就知道Provider本质上是一个Properties文件,里面的kv存储着引擎名和具体算法类的实现。

可以通过下面的程序示例查看具体的提供者引擎和算法:

其输出如下,(截取部分)

值得一提的是引擎类的结构设计。如上所说,引擎类除了给业务开发人员提供接口,还有一个任务就是要为第三方提供者使用。引擎为提供者提供了一个接口——SPI(security provider interface)。

还是以MessageDigest为例(这是消息摘要引擎)。MessageDigest继承了MessageDigestSpi。MessageDigestSpi抽象类定义了消息摘要引擎要做的事情。MessageDigest内部持有一个Delegate委托类,MessageDigest的核心方法就是getInstance()获取类的实例,实现见下:

通过Security.getImpl()反射获取到对应的provider和算法实现类,并通过类型判断和else委托逻辑保证返回一个MessageDigest实例。

再具体一点,以Sun security提供的MD5算法实现为例。虽然MD5并没有直接实现MessageDigestSpi,但MD5的父类DigestBase继承了MessageDigestSpi。所以实际上还是满足这个架构的设计。DigestBase做了消息摘要通用的实现,留了三个abstract接口:

这几个代码在MD5中具体实现:(截取部分)

最后补充一个类图说明下类的结构:

下一篇: 方法的调用