11.2 基础知识

Hadoop RPC中采用了SASL(Simple Authentication and Security Layer,简单认证和安全层)进行安全认证,具体认证方法涉及DIGEST-MD5和Kerberos两种。本节详细介绍SASL、DIGEST-MD5和Kerberos的基本概念和原理。

11.2.1 安全认证机制

1.SASL

SASL是一种用来扩充C/S模式验证能力的认证机制。它的核心思想是把用户认证和安全传输从应用程序中隔离出来。比如SMTP(Simple Mail Transfer Protocol,简单邮件传输协议)在定义之初没有考虑到用户认证等问题,现在SMTP可以使用SASL来完成这方面的工作。

SASL支持多种认证方法,主要包括以下几种。

❑ANONYMOUS:无须认证。

❑PLAIN:最简单的机制,但同时也是最危险的机制,因为信息采用明文密码方式传输。

❑DIGEST-MD5:这是一种HTTP Digest兼容的安全机制,基于MD5,可以提供数据的安全传输层。这是方便性和安全性结合得最好的一种方式,也是SASL默认采用的方式。使用这种机制时,客户端与服务器端共享同一个密钥,而且该密钥不通过网络传输。验证过程是从服务器端先提出“质询”(实际上是一组信息)开始,客户端使用此“质询”与密钥计算出一个应答。不同的“质询”,不可能计算出相同的应答,且任何拥有密钥的一方,都可以用相同的“质询”算出相同的应答。因此,服务器端只要比较客户端返回的应答与自己算出的应答是否相同,就可以知道客户端所拥有的密钥是否正确。由于真正的密钥并没有通过网络进行传输,所以不怕网络窃取。

❑GSSAPI:Generic Security Services Application Program Interface(通用安全服务应用程序接口)。GSSAPI本身是一套API,由IETF(Internet Engineering Task Force,互联网工程任务组)标准化。由于其最主要的实现是基于Kerberos的,所以一般说到GSSAPI都暗指Kerberos实现。我们将在下一小节对Kerberos进行详细介绍。

2.JAAS

JAAS(Java Authentication and Authorization Service, Java认证和授权服务)是SUN公司为了增强Java 2安全框架中的功能而提供的编程接口。Java 2安全框架提供的是基于代码源的存取控制方式,而JAAS还提供了基于代码运行者的存取控制能力,因此,JAAS是Java安全编程的一个重要补充。随着Internet安全问题越来越受到重视,JAAS在Java应用编程中得到了越来越广泛的应用。

JAAS主要由认证和授权两大部分构成。认证就是简单地对一个实体的身份进行判断;而授权则是向实体授予对数据资源和信息访问权限的决策过程。从1.4版本开始,JDK已经开始集成JAAS。

JAAS认证通过插件的形式工作,这使得Java应用程序独立于底层的认证技术,应用程序可以使用新的或经过修改的认证技术而不需要修改应用程序本身。应用程序通过实例化一个登录上下文对象来开始认证过程,这个对象根据配置决定采用哪个登录模块,而登录模块决定了认证技术和登录方式。一个比较典型的登录方式是提示输入用户名和口令,其他登录方式还有读入并核实声音或指纹样本。

JAAS的核心类可以分为公共类、认证类和授权类三部分。其中,公共类包括Subject、Principal、Credential三个类;认证类包括LoginContext、LoginModule、CallbackHandler和Callback四个类;授权类包括Policy、AuthPermission和PrivateCrtx]entialPermission三个类。在Hadoop中仅用到了公共类和认证类,接下来我们分别对其进行介绍。

(1)公共类

公共类是由JAAS认证和授权的部分共同使用的类。其中Subject类最关键,它代表某个整体的一组相关信息,这个整体可以是一个人或其他对象,而相关信息则包括这个整体的标识(Principal)、公有凭据、私有凭据等。JAAS的标识类必须实现java.security.Principal接口,但凭据(Credential)类可以是任何对象。

Subject类

应用程序首先要对请求的来源进行认证,然后才能对该请求源访问的资源进行授权。JAAS框架定义“主题”这个术语代表请求源。主题可以是任何实体,如一个人或一项服务。一旦通过了认证,主题就和相关的标识联系在一起。标识可以使不同主题之间相互区别。一个主题可以具有多个标识,例如,一个人可以有一个名字标识和一个身份证号标识。主题也可以拥有与安全相关的属性,这些属性被称为凭据。需要特殊保护的凭据,如私钥,储存在私有凭据集合中;而可以公开的凭据,如公共证书,则储存在公共的凭据集合中。

主题类有以下几个比较重要的方法:


public Set getPrincipals();//返回所有标识;

public static Object doAs(final Subject subject, final PrivilegedAction action);

//以某一主题身份执行action实例的run方法,如果正常执行,返回从run方法所返回的对象


Principal类

一个Principal对象可以和一个Subject对象关联,用于区别不同的主题(Subject)。用户自定义的Principal类必须实现Principal和Serializable接口。我们可以用Principal类提供的getPrincipals方法得到和更新与一个主题相联系的标识。

Credential类

Credential类通常用于实现一个凭据。凭据通常分为两种,分别是公共和私有凭据。核心JAAS类库没有对公共和私有凭据类做出规定,所以任何Java类都能代表凭据。但一般情况下,建议作为凭据的类应该实现Refreshable和Destroyable两个接口。Refreshable接口可以使凭据能够自我刷新,而Destroyable接口提供了销毁凭据中内容的功能。

(2)认证类

对一个主题进行认证需要以下步骤:

步骤1 应用程序实例化登录上下文(LoginContext)。

步骤2 登录上下文按照输入参数及配置装入所有相关的登录模块。

步骤3 应用程序调用登录上下文的Login方法。

步骤4 Login方法调用所有被装入的登录模块。每个模块都试图认证主题。如果认证成功,登录模块就把相关的标识和凭据关联到所认证的主题。

步骤5 登录上下文返回认证状态给应用程序。

步骤6 如果认证成功,应用程序可以从登录上下文中获得被认证的主题。

LoginContext类

LoginContext,即登录上下文类,给应用程序提供了认证主题的基本方法,并提供了一种独立于底层认证技术的应用程序开发方法。登录上下文依照配置决定应用程序采用哪些认证模块,这样,认证模块就以插件的形式工作于应用程序的底层,而认证技术的改变不需要修改应用程序本身。

LoginModule类

LoginModule类使开发者能够把不同类型的认证技术以插件的形式加到应用程序中。该类中最重要的方法是login(),定义如下:


boolean login()throws LoginException;


Login方法将由登录上下文自动调用,此时登录模块开始认证过程。

CallbackHandler类

登录过程的身份验证方式由用户所编写的CallbackHandler类决定。该类的实现既可以是提示用户输入用户名和密码,也可以是从智能卡或生物特征鉴别设备那里得到数据,或者简单地从底层的操作系统中抽取用户信息。

在某些情况下,登录模块必须和用户通信以获得认证信息,期间涉及的通信过程如下:

步骤1 应用程序提供一个实现CallbackHandler接口的类,并把该类实例的引用作为创建登录上下文对象时的参数。

步骤2 登录上下文接着把CallbackHandler类传给底层的登录模块。

步骤3 登录模块通过这个引用调用它的Handle方法,这样就可以从用户那里获取认证信息,也可以把信息送给用户。

由此可见,底层的登录模块与用户交互的方式完全是由应用程序决定的。

JAAS库中自带了一些认证机制,包括Windows NT、LDAP(Lightweight Directory Access Protocol,轻量目录访问协议)、Kerberos等,而Hadoop则主要采用了Kerberos。