内容


XML 安全

使用 SPML 有效地进行身份管理

服务配置标记语言的目标、架构和基本概念

系列内容:

此内容是该系列 # 部分中的第 # 部分: XML 安全

敬请期待该系列的后续内容。

此内容是该系列的一部分:XML 安全

敬请期待该系列的后续内容。

过去两年中,人们对身份管理的兴趣不断增长。切实有效地管理身份是商业中至关重要的一个问题,人们提出了不同的标准解决身份管理的不同方面(请参阅 什么是身份管理?)。服务配置标记语言(SPML)就是其中的一个标准,它解决的是这些身份的资源配置。它为那些实现业务活动的装备 IT 基础设施和支持基础设施这类普通但又容易出错的任务制定了标准。比如,当组织雇用新的员工时 SPML 可以实现配置工作流的自动化。

配置工作流可以包含数字活动或物理活动。比方说,雇用新员工时,数字活动可能包括在不同的系统和应用程序中,以便创建用户帐号,而物理活动可能包括为新员工申请膝上型电脑。

本文将探讨 SPML 标准的目标和重要意义。我将引导您创建一些示例程序,示范该标准如何能够帮助实现配置活动的自动化。示例代码使用的是 openSPML,它是 SPML 的开放源代码实现。

为何要使用 SPML

真的需要为配置制定一种标准吗?当然,设想一下拥有成千上万员工和大量 IT 系统、应用程序和外部伙伴系统的大公司,想一想公司合并、新的应用程序投入生产或者新员工加入公司所引起的 IT 配置问题。IT 配置问题既包括数字领域的问题,如授予计算机系统、文件、目录或大楼的访问权;也包括物理领域的问题,如为新员工申请膝上型电脑、蜂窝电话或者办公桌椅。现在,考虑当员工离开或者终止业务关系时必须立刻完成的事情,以确保公司资产不会被前员工或业务伙伴非法使用。

通过这些问题您就会理解为何配置这么重要了。但是,为何组织之间需要使用一种统一的 标准 呢?在这个互相联系的世界中,组织的供应链交织在一起,越来越多地互相使用对方的系统,以便通过资源组合获得最大的效能和生产率。使用统一的标准有助于跨越不同组织和异构系统实现配置管理。

要实现什么样的目标

SPML的目标包括:

  • 自动化 IT 配置任务:通过标准化配置工作,使其更容易封装配置系统的安全和审计需求,SPML 致力于推动配置的自动化。
  • 不同配置系统之间的互操作性:不同的配置系统可以公开标准的 SPML 接口,实现互操作。

配置系统的组成和各部分之间的关系

配制系统包括三个基本组成部分:请求机构(Requesting Authority,RA)、配置服务点(Provisioning Service Point,PSP)和配置服务目标(Provisioning Service Target,PST),如图 1 所示:

图 1. SPML 架构
SPML 架构
SPML 架构
  • 请求机构(RA):SPML 方案中的客户。它创建形式良好的 SPML 文档并作为请求发送给 SPML 服务点。这些请求描述了在特定服务点上执行的操作。RA 向 SPML 服务点发送请求,要求 RA 和 SPML 服务点之间存在信任关系。每个 SPML 服务点都可以作为 RA 向其他服务点发送 SPML 请求。
  • 配置服务点(PSP):这部分负责监听并处理来自 RA 的请求,然后将响应返回给 RA。监听和处理结构良好的 SPML 文档的任何组件都称为配置服务点。
  • 配置服务目标(PST):实际执行动作的软件。比如,存储组织用户帐号的 LDAP 目录,或者用于记录 IT 请求(比如为新员工申请膝上型电脑)的 IT 票证系统。

可以看出,SPML 管理的基本架构包括客户(RS)、服务器(PSP)和资源(PST)。此外,一台服务器还可以作为其他服务器的客户机,依此类推。

探索 SPML

现在我们将深入 SPML 标准去看看。要知道这仅仅是 1.0 版,所以不要期望其功能非常完善。2.0 版正在开发之中,预计将提供更多非常好的特性。

SPML 中定义了三部分内容:

  • 一组核心操作
  • 请求应答协议
  • 服务模式定义

SPML和新操作

SPML 1.0 规范中定义了以下核心操作:Add、Modify、Delete 和 Search。基本上意味着所有 PST 都会通过 SPML 定义的接口提供这 4 种操作。

为了便于理解,我们假设您是一位系统管理员,正要添加新的员工。该员工必须能够访问另外某个人管理的故障通知单系统。将新员工注册到该故障通知单系统的一种办法是向系统的所有者发送电子邮件或者打电话,然后等待答复。SPML 提供了结构化的自动方法处理这类请求。通过 SPML 可以使用故障通知单系统的 4 种核心操作,因此只需要用 Add 方法将这个新员工添加到那个系统中即可。

离开这个话题之前再提一点:SPML 1.0 允许为服务定义上述 4 种核心操作之外的其他操作。这些操作称为 扩展操作,允许客户机使用预定义的语法和语义发送请求和接收响应。

SPML 请求应答协议

SPML 请求应答协议涉及到不同的 SPML 部分如何互相对话,主要是客户机(RA)和服务器(PSP)。该协议规定客户机发送的请求必须描述在特定服务点上执行的一个或多个操作。请求可以单独提交也可以成批提交,两种请求类型都可以选择同步或异步提交方式。

要彻底理解请求应答协议,则需要深入了解它以下两个不同方面:

  • 请求执行模型(同步或异步)
  • 请求分组(单个或成批)

请求执行模型
首先看看 SPML 如何规定对请求的同步和异步执行的支持。同步处理的请求会阻塞调用。RA 保持其执行调用处于打开状态,直到收到对该调用的响应。在异步执行的请求中,执行模型稍微复杂一点。首先,RA 用惟一的请求 ID 发出每个请求,不等待同一执行调用的响应。在请求执行期间,PSP 负责维护请求 ID,准备好响应之后随着响应一起返回。请求处理过程中,客户机可能希望知道请求的状态,通过请求 ID 可以很容易实现这一点。请求 ID 还用于控制和管理服务器上待执行和执行中的 SPML 请求。

SPML 提供了两种操作来管理和控制异步请求执行:

  • StatusRequest——该操作允许客户端获得异步执行的请求的当前状态。 StatusRequest 操作的一个变量不仅允许客户端能得到当前的结果,如果可用的话,还可以得到当前的结果集。
  • CancelRequest——该操作允许 RA 取消执行尚未执行的异步请求。

请求分组
RA 可以逐个发送请求也可以成批发送请求。无论哪种情况,请求都有同步和异步两种执行方式。单个请求可使用标准方式处理,而成批请求则有些古怪,您需要对此有所了解。

您可能已经知道,成批请求就是成组的多个请求。对成批处理,了解以下三点很重要:

  • 如何在一次批处理中返回每个请求的结果。
  • 如何处理多个请求(并行还是顺序处理)。
  • 成批请求失败时如何处理错误。

我将在 SPML 上下文中解释这三个问题。

结果处理:将多个 SPML 操作结合在一起,并将它们作为单个 BatchRequest 发出。PSP 的处理结果是按照位置对应关系作为单个 BatchResponse 发送的,也就是说, BatchResponse 中的第一个响应对应 BatchRequest 中的第一个请求,第二个响应对应第二个请求,依此类推。

处理类型:SPML 同时支持并行和顺序处理请求。RA 可以决定如何处理。如果使用顺序处理,请求按照成批请求中出现的顺序依次处理。如果使用并行处理,服务器可以按照任何顺序执行成批请求。但是无论是哪种情况,响应都由位置对应关系决定。

错误处理: 如果成批请求中某些失败,SPML 会提供两种选择来处理这种情况:恢复和退出。RA 在发出成批请求时规定一个首选项。如果要求服务器恢复,单个操作的失败不会影响剩余请求的处理,并仍然保持位置对应关系。如果要求退出,一旦遇到错误,服务器就终止剩余请求的处理,所有未执行的请求都标记为失败。

SPML 服务模式定义

服务模式允许客户机咨询 SPML 它支持的操作的细节。

SPML 服务模式以 W3C XML Schema 为基础,并将其增加到对象类型定义和属性共享模型中(请参阅 对象类和属性共享模型)。 清单 1 所示的实例服务模式中,要注意属性是如何采用 XML Schema 风格定义的。还可以看到属性如何组织在 ObjectClassDefinition 下。本文后面的 SPML 示例代码将使用同一个服务模式。

清单 1: 服务模式
<schema majorVersion="1" minorVersion="0">
<providerIdentifier providerIDType="urn:oasis:names:tc:SPML:1:0#URN">
<providerID>urn:oasis:names:tc:SecF</providerID>
</providerIdentifier>
<schemaIdentifier schemaIDType="urn:oasis:names:tc:SPML:1:0#GenericString">
<schemaID>PersonSchema</schemaID>
</schemaIdentifier>
<attributeDefinition name="FullName" 
                     description="Full name of the employee joining."/>
<attributeDefinition name="email" description="E-mail address."/>
<attributeDefinition name="description" description="Description."/>
<attributeDefinition name="project" description="Project assigned to."/>
<objectclassDefinition name="employee" description="Sample employee.">
<memberAttributes>
<attributeDefinitionReference name="FullName" required="true"/>
<attributeDefinitionReference name="email" required="true"/>
<attributeDefinitionReference name="description"/>
<attributeDefinitionReference name="project" required="true"/>
</memberAttributes>
</objectclassDefinition>
</schema>

客户机使用上述的请求应答协议获得模式信息。SPML 中定义的用于获取模式信息的操作称为 SchemaRequestSchemaRequest 用于检索特定配置模式。这些模式使用标识符检索,具体地说,是使用 提供者标识符模式标识符。如果没有提供模式标识符,则返回该提供者支持的所有模式。提供者标识符是提供者的惟一标识符,提供者可以是一个组织或者负责一组操作的某个人。模式描述符是提供者指定的惟一模式标识符。其惟一性在提供者上下文中得到保证。

亲自动手试试

这一节将介绍一些 SPML 示例代码。目标是为新员工创建一个电子邮件帐号。假设您作为人力资源部门(HR)的代表,希望为新员工创建一个电子邮件帐号。您给邮件服务器管理员打电话,交谈记录如下:

您:组织新进了一位员工,我希望创建他的电子邮件帐号,设置电子邮件帐号需要我提供哪些信息?
管理员:请告诉我员工的全名、希望使用的电子邮件 ID、工作角色和职责的描述,他将参与的项目。
您:好的。(提供了需要的详细信息)。请告诉我帐号什么时候能建好,使用该帐号有哪些限制。
管理员: 邮件帐号建好后我会通知您,还会发送一份详细的使用条款。

在 SPML 世界中,对话变成了两个系统之间的 SOAP 编码的 SPML 消息交换,即 HR 系统和创建新员工电子邮件帐号的邮件服务器。SMPL 消息交换的顺序如下。

SPML 消息 1: HR 系统(RA)向负责管理邮件服务器(PST)的 PSP 发送 SchemaRequest,看看创建新帐号邮件服务器需要什么信息。
SPML 消息 2: PSP 将 SchemaResponse 发送给 HR 系统。这个 SchemaResponse 包含邮件服务器(PST)创建邮件帐号所需要的详细信息。

清单 2 显示了同步执行模式下 SchemaRequestSchemaResponse 的创建。该例中使用配置模式(SchemaResponse.xml)放在资源包(请参阅 参考资料)中可以下载。

下面的 SchemaRequest 代码片段显示了一般 SchemaRequest 的创建,就是说没有规定提供者 ID 和模式 ID。PSP 使用的所有模式都返回给 RA。不过该例中仅返回一个模式,因为我在 PSP 中只规定了一个模式。

清单 2: SchemaRequest 和 SchemaResponse
public class UseSPML {
    private static void mySchemaRequest(SpmlClient client) {
        SchemaRequest schemaRequest = new SchemaRequest();
        try {
            SchemaResponse schemaResponse = (SchemaResponse) client
                        .request(schemaRequest);
        } catch (SpmlException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
    }
    public static void main(String[] args) {
        SpmlClient client = new SpmlClient();
        try {
            // Replace the URL with the one where your SPML server
// might be running
            client.setUrl("http://localhost:8080/spml");
        } catch (MalformedURLException e1) {
            // TODO Auto-generated catch block
            e1.printStackTrace();
        }
        client.setTrace(true);
        mySchemaRequest(client);
    }
}
// Handling of SchemaRequest by PSP and generation of SchemaResponse.
// Schema returned in SchemaResponse is read from a file named 
// SchemaResponse.xml. 
// This file is available for download as part of the resource bundle.
public class SPMLServer implements SpmlHandler {
    public SpmlResponse doRequest(SpmlRequest request) {
        SpmlResponse response = null;
        if (request instanceof SchemaRequest) {
            response = (SchemaResponse) ((SchemaRequest) request)
                            .createResponse();
            try {
                        ((SchemaResponse) response).addSchema(new Schema(
                            readFile("SchemaResponse.xml")));
            } catch (SpmlException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
            }
        }
    }
    private static String readFile(String fileName) {
        FileReader fr = null;
        try {
            fr = new FileReader(fileName);
        } catch (FileNotFoundException e1) {
            // TODO Auto-generated catch block
            e1.printStackTrace();
        }
        BufferedReader br = new BufferedReader(fr);
        StringBuffer fileBuffer = new StringBuffer();
        String rec = new String();
        try {
            while ((rec = br.readLine()) != null) {
                        fileBuffer = fileBuffer.append(rec);
            }
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return fileBuffer.toString();
    }
}

清单 2 可以看出,类 SPMLServerdoRequest 方法返回从文件 SchemaResponse.xml 读取的 SchemaResponse

SPML 消息 3:根据从 SchemaResponse 中检索的模式,HR 系统(RA)向 PSP 发送 AddRequest 来添加新的电子邮件帐号。
SPML 消息 4:PSP 直接调用服务器 API 或者通过向电子邮件服务器发送 SPML AddRequest 消息,以便启动创建电子邮件帐号的过程。在 清单 3 中,PSP 仅仅在一个文件中记录电子邮件帐号创建的细节。PSP 向 HR 系统返回 AddResponse 消息,其中包含应用限制的规范。

清单 3 显示了 RA 和 PSP 之间交换的 AddRequestAddResponse 消息。我为一个名为“Manish Verma”的用户创建了邮件帐号。在响应中,PSP 发送创建的邮件 ID 和邮箱的大小限制。

清单 3 AddRequest 和 AddResponse
public class UseSPML {
    private static void myAddRequest(SpmlClient client) {
        AddRequest req = new AddRequest();
        req.setObjectClass("urn:oasis:names:tc:SPML:PersonSchema:employee");
        req.setIdentifier("spmlserver");
        req.setAttribute("FullName", "Manish Verma");
        req.setAttribute("email", "mverma@secf.com");
        req.setAttribute("description", "Center Head");
        req.setAttribute("Project", "SecF India");
        try {
            AddResponse response = (AddResponse) client.request(req);
        } catch (SpmlException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
    public static void main(String[] args) {
        SpmlClient client = new SpmlClient();
        try {
            // Replace the URL with the one where your SPML server 
            // might be running
            client.setUrl("http://localhost:8080/spml");
        } catch (MalformedURLException e1) {
            // TODO Auto-generated catch block
            e1.printStackTrace();
        }
        client.setTrace(true);
        myAddRequest(client);
    }
}
Handling of AddRequest by  PSP and generation of AddResponse
public class SPMLServer implements SpmlHandler {
	
    public SpmlResponse doRequest(SpmlRequest request) {
        SpmlResponse response = null;
        if (request instanceof AddRequest) {
            List attributes = ((AddRequest) request).getAttributes();
            BufferedWriter bw = null;
            try {
                bw = new BufferedWriter(new FileWriter(
                        "C:\\work\\SPML\\addreqdoc.txt"));
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            StringBuffer addRequestString = new StringBuffer("AddRequest ");
            addRequestString.append(writeln(""));
            for (int i = 0; i < attributes.size(); i++) {
                addRequestString.append(((Attribute) attributes.get(i))
                        .getName());
                addRequestString.append(" ");
                addRequestString.append(((Attribute) attributes.get(i))
                        .getValue());
                addRequestString.append(writeln(""));
            }
            try {
                bw.write(addRequestString.toString());
                bw.close();
            } catch (IOException e1) {
                // TODO Auto-generated catch block
                e1.printStackTrace();
            }
            response = (AddResponse) ((AddRequest) request).createResponse();
            Identifier addResponseId = new Identifier();
            addResponseId.setType(Identifier.TYPE_EMailAddress);
            addResponseId.setId((String) ((AddRequest) request)
                        .getAttributeValue("email")); 
            ((AddResponse) response).setIdentifier(addResponseId);
            ((AddResponse) response).setAttribute("MailBoxLimit", "500MB");
        }
        return response;
    }
    // utility method that puts line separator characters to the end 
    // of the input string
    private static String writeln(String string) {
        String lineSeparator = System.getProperty("line.separator");
        return string + lineSeparator;
    }
}

可以从 参考资料下载完整的代码。要执行和使用这些例子,首先要安装并配置 openSPML。然后用资源包( org.eklavya.spml.SpmlServer)中提供的 SpmlHandler 代替默认的 openSPML PSP( org.openspml.test.TestSpmlHandler)。SPML 客户机是类 org.eklavya.spml.UseSpml。此外,还要修改这两个文件中的设置,使其和您的设置匹配。

结束语

现在您了解了配置适合于整个身份管理领域,也认识到了采用 SPML 作为标准在自动化和互操作性方面带来的好处。现在,您已经了解了使用 OpenSPML 配置 SPML 服务器以及如何交换 SPML 消息。

我建议您采用这项技术,并不断加深对该标准的理解。一旦您的公司讨论使用该标准或者要实现身份管理,您就可以利用对 SPML 的认识和了解来创造价值。


下载资源


相关主题

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=10
Zone=XML
ArticleID=58182
ArticleTitle=XML 安全: 使用 SPML 有效地进行身份管理
publish-date=01012005