使用 UDDI V3 API 构建安全的 UDDI 应用

本文主要介绍了 IBM UDDI 的安全选项配置以及对应的 UDDI V3 API 的使用。深入剖析了 IBM UDDI 中的 UDDI Publishers, APIs 等高级选项的配置。在文章中,作者给出了使用 UDDI V3 API 与用户个性化安全选项配置协同工作的代码片段。对于不同厂商的 UDDI 产品对 UDDI V3 API 的不同的需求,本文也有涉及。在文章的下载部分,读者可以下载完整的代码来学习 UDDI V3 API 的使用。

介绍

IBM UDDI 是作为 WebSphere 应用服务器的应用程序来发布的。用户可以按照 WebSphere 应用服务器信息中心的步骤(http://publib.boulder.ibm.com/infocenter/wasinfo/v6r0/index.jsp?topic=/com.ibm.websphere.express.doc/info/exp/ae/twsu_default_install2.html)来安装一个 UDDI 服务器。IBM UDDI 可以利用 WebSphere 应用服务器的安全机制来构建自己的安全框架。IBM UDDI 也可以使用 authentication token 来进行安全的查询,发布等操作。

  • 平台安全机制
    • 授权

      授权决定了哪一个用户可以访问何种服务。WebSphere 应用服务器对用户,或者一组用户授予对应的用户角色。预定义的常用用户角色如图 1 所示。

      • GUI_Publish_User/GUI_Inquiry_User 是从网页界面来访问 UDDI 的用户角色 , 例如界面 http://localhost:9080/uddigui。
      • SOAP_Publish_User/SOAP_Inquiry_User 是出于兼容性考虑为使用 UDDI V1,UDDI V2 API 的用户保留的用户角色。
      • EJB_Inquiry_Role/EJB_Publish_Role 是使用 EJB 访问的用户角色。
      • V3SOAP_Inquiry_User_Role/V3SOAP_Publish_User_Role/V3SOAP_CustodyTransfer_User_Role/V3SOAP_Security_User_Role 是使用 UDDI V3 API 的用户角色。
图 1. UDDI 用户与用户角色对应关系 使用 UDDI V3 API 构建安全的 UDDI 应用_第1张图片
    • 数据保密

数据保密保证了在网络传输层的数据安全性。WebSphere 应用服务器的数据安全性可以是“无“(使用 HTTP 作为传输协议)或者“保密”(需要使用安全套接字协议 SSL 使用 HTTPS 作为传输协议)。通常的获得数据保密性的方法是使用 SSL 协议。SSL 协议为 WebSphere 应用服务器上的客户端和服务器端的安全连接提供了传输层的安全性。SSL 通过对数据加密避免了在数据传输时泄露敏感信息。数字签名则保证了数据传输时数据不会被篡改。客户端和服务器端的认证保证了用户同正确的用户和机器在进行交互。用户需要对 UDDI 发布 API 设置用户名,密码;对 UDDI 查询 API 则不需要设置用户名,密码。

UDDI_Publication_PortType publishPort; 
//Get UDDI_Publication_PortType from UDDI_Service
((javax.xml.rpc.Stub) publishPort)
._setProperty(javax.xml.rpc.Stub.USERNAME_PROPERTY, user); 
((javax.xml.rpc.Stub) publishPort)
._setProperty(javax.xml.rpc.Stub.PASSWORD_PROPERTY, password); 
  • UDDI 安全机制

UDDI 标准建议使用在 UDDI API 上使用 authentication token 来保证安全性。下文是 UDDI 第三版规范中关于 authentication token 的摘录:

The security API includes the following API calls: • discard_authToken: Used to inform a node that a previously obtained authentication token is no longer required and should be considered invalid if used after this message is received. • get_authToken: Used to request an authentication token in the form of an authInfo element from a UDDI node. An authInfo element MAY be required when using the API calls defined in Section 5.1 Inquiry API Set, Section 5.2 Publication API Set, Section 5.4 Custody and Ownership Transfer API Set, and Section 5.5 Subscription API Set.

当用户需要做 UDDI 查询 / 发布操作时,用户可以在 API 上设置从 Get_authToken 获得的 authentication token。当然用户需先对 Get_authToken 设置用户 / 密码,然后才能获取 authentication token。

org.uddi.v3.schema.api.Get_authToken getAuthToken = new Get_authToken();
getAuthToken.setUserID(username); 
getAuthToken.setCred(password); 
AuthToken authToken =(UDDI_Security_PortType)securityPort.get_authToken(getAuthToken);

对于每一个查询 / 发布 API,它含有如图 2 所示的 authInfo 参数。

图 2. save_business API 使用 UDDI V3 API 构建安全的 UDDI 应用_第2张图片

save_business 调用被用来存储或者更新一个 businessEntity 上的信息。authInfo 这个可选的参数是一个包含 authentication token 的元素。authentication token 可以通过 get_authToken API 或者 UDDI 规范之外的方法获得。当 UDDI 服务器有多个发布者或者需要限制哪一个发布者可以发布信息时,就需要在 API 上设置 authInfo。用户可以用如下代码来保证 save_business API 的安全:

Save_business saveBusiness = new Save_business();
saveBusiness.setAuthInfo(authToken.getAuthInfo());

当 UDDI 服务器接收到来自客户端的一个 Save_business 请求后,它首先要判断 authentication token 里包含的用户名 / 密码信息是不是同 UDDI 服务器上注册用户信息一致,如果一致,则成功保存 businessEntity。

回页首

访问开启平台安全的 UDDI

如果用户想连接开启平台安全的 UDDI,用户需要在 WebSphere Application Server 控制台下开启安全。在 Security>Secure administration, applications, and infrastructure 下确保 administrative security 和 application security 已被开启。用户可以参照 WebSphere Application Server 信息中心来获得更多的信息。

图 3. WebSphere Application Server 安全设置 使用 UDDI V3 API 构建安全的 UDDI 应用_第3张图片

当 UDDI 的平台安全打开后,用户可以在 Enterprise Applications>UDDIRegistry.UDDINode.server1>Security role to user/group mapping 下察看默认的安全设置。在默认设置下,V3SOAP_Inquiry_User_Role 被授权给“Everyone”,说明任何用户都可以从 UDDI 中查寻内容;V3SOAP_Publish_User_Role 被授权给“All authenticated”,说明只有被授权的用户才能向 UDDI 中发布内容。详细信息请参见图1。

如果用户想向打开平台安全的 UDDI 发布或查询内容时,可以通过以下方式:

  1. 获取 ServiceFactory UDDI_Service
    ServiceFactory factory = ServiceFactory.newInstance();
    UDDI_ServiceuddiService =(UDDI_Service)factory.loadService(UDDI_Service.class);
    
  2. 获取 UDDI_Publication_PortTypeUDDI_Inquiry_PortType
    UDDI_Publication_PortType publishPort = uddiService.getUDDI_Publication_Port();
    UDDI_Inquiry_PortType inquiryPort = uddiService.getUDDI_Inquiry_Port();
    
  3. 设置 publish URL, inquiry URL 和安全信息 (username, password, trustStore, trustStore password, keyStore and keyStore password)。
    (((Stub) publishPort)._setProperty(Stub.ENDPOINT_ADDRESS_PROPERTY, publishURL);
    ((Stub) publishPort)._setProperty(Stub.USERNAME_PROPERTY, userName);
    ((Stub) publishPort)._setProperty(Stub.PASSWORD_PROPERTY, password);
    
    ((Stub)inquiryPort)._setProperty(Stub.ENDPOINT_ADDRESS_PROPERTY, inquiryURL);
    ((Stub) inquiryPort)._setProperty(Stub.USERNAME_PROPERTY, userName);
    ((Stub) inquiryPort)._setProperty(Stub.PASSWORD_PROPERTY, password);
    
    System.setProperty("javax.net.ssl.trustStore", trustStore);
    System.setProperty("javax.net.ssl.trustStorePassword", trustStorePassword);
    System.setProperty("javax.net.ssl.keyStore", keyStore);
    System.setProperty("javax.net.ssl.keyStorePassword", keyStorePassword); 
    
  4. 向 UDDI 发布内容。
     Name businessName[] = new Name[1];
    businessName[0] = new Name();
    businessName[0].set_value("BusinessEntity");
    BusinessEntity newBusinesses[] = new BusinessEntity[1];
    newBusinesses[0] = new BusinessEntity();
    newBusinesses[0].setName(businessName);
    Save_business saveBusiness = new Save_business();
    saveBusiness.setBusinessEntity(newBusinesses);
    BusinessDetail businessDetail = publishPort.save_business(saveBusiness);
    URI businessKey = businessDetail.getBusinessEntity(0).getBusinessKey();
    if (businessKey == null) {
    System.out.println("Publish failed.");
    }else{
    System.out.println("Publish succeeded.");
    } 
    
  5. 从 UDDI 中获取内容。
     businessName[0] = new Name();
    businessName[0].set_value("BusinessEntity");
    Find_business findBusiness = new Find_business();
    findBusiness.setName(businessName);
    BusinessList businessList = inquiryPort.find_business(findBusiness);
    BusinessInfos businessInfos = businessList.getBusinessInfos();
    if (businessInfos == null || businessInfos.getBusinessInfo().length == 0) {
    System.out.println("Inquiry failed.");
    }else{
    System.out.println("Inquiry succeeded.");
    } 
    

    注意 :

  6. 关于 V3SOAP_Inquiry_User_Role 的设置 :
    1. 如果“EveryOne”和“All authenticated”都没有被选中会出现错误“(403) Forbidden”。
    2. 如果“EveryOne”被选中,所有的用户都可以从 UDDI 中查寻内容,这时并不需要向 inquiry port 设置用户名和密码。
    3. 如果“All authenticated”被选中,只有被授权的用户才有权限从 UDDI 中查寻内容,这时必须向 inquiry port 设置用户名和密码。如果使用非授权的用户查询会出现错误“(401) Unauthorized”。 
  7. 关于 V3SOAP_Publish_User_Role 的设置 :
    1. 如果“EveryOne”和“All authenticated”都没有被选中 , 错误“(403) Forbidden”会出现。
    2. 如果“EveryOne”被选中会出现 UDDI 错误 10120。
    3. 如果“All authenticated”被选中,只有被授权的用户才有权限向 UDDI 中发布内容,这时必须向 publish port 设置用户名和密码。如果使用非授权的用户发布会出现错误“(401)。
回页首

访问开启 UDDI 安全的 UDDI

UDDI 使用 authentication token 来限制用户的查询和发布操作,以 IBM 的 UDDI 为例,有三个配置选项和 authentication token 有关,他们分别是:

  • Use authInfo credentials if provided
  • Authentication token expiry period
  • Automatically register UDDI publishers

如图 4 所示,这些配置选项可以在 WAS 控制台 WAS console>UDDI Nodes 中找到,图 4 是默认配置,表明采用 authentication token 中的信息来进行 UDDI 操作,同时 authentication token 的过期时间为 30 分钟。

图 4. UDDI 安全配置选项 使用 UDDI V3 API 构建安全的 UDDI 应用_第4张图片

在这样的安全配置下 , 用户可以采用如下的方式在 UDDI 中查询和发布内容:

  1. 获取 ServiceFactory UDDI_Service
    ServiceFactory factory = ServiceFactory.newInstance();
    UDDI_ServiceuddiService =(UDDI_Service)factory.loadService(UDDI_Service.class);
    
  2. 获取 UDDI Publication, Inquiry, Security PortType
    UDDI_Publication_PortType publishPort = uddiService.getUDDI_Publication_Port();
    UDDI_Inquiry_PortType inquiryPort = uddiService.getUDDI_Inquiry_Port();
    UDDI_Security_PortType securityPort = uddiService.getUDDI_Security_Port();
    
  3. 设置 publish URL, inquiry URL 和 security URL。
    ((Stub) publishPort)._setProperty(Stub.ENDPOINT_ADDRESS_PROPERTY, publishURL);
    ((Stub)inquiryPort)._setProperty(Stub.ENDPOINT_ADDRESS_PROPERTY, inquiryURL);
    ((Stub) securityPort)._setProperty(Stub.ENDPOINT_ADDRESS_PROPERTY, securityURL); 
    
  4. 获取 authentication token。
    Get_authToken getAuthToken = new Get_authToken();
    getAuthToken.setUserID(userName);
    getAuthToken.setCred(password);
    AuthToken authToken = null;
    authToken = securityPort.get_authToken(getAuthToken); 
    
  5. 使用 authenticate token 往 UDDI 中发布内容。
    Name businessName[] = new Name[1];
    businessName[0] = new Name();
    businessName[0].set_value("BusinessEntity");
    BusinessEntity newBusinesses[] = new BusinessEntity[1];
    newBusinesses[0] = new BusinessEntity();
    newBusinesses[0].setName(businessName);
    Save_business saveBusiness = new Save_business();
    saveBusiness.setBusinessEntity(newBusinesses);
    saveBusiness.setAuthInfo(authToken.getAuthInfo());
    BusinessDetail businessDetail = publishPort.save_business(saveBusiness);
    URI businessKey = businessDetail.getBusinessEntity(0).getBusinessKey();
    if (businessKey == null) {
    System.out.println("Publish failed.");
    }else{
    System.out.println("Publish succeeded.");
    } 
    
  6. 使用 authenticate token 从 UDDI 中获取内容。
     businessName[0] = new Name();
    businessName[0].set_value("BusinessEntity");
    Find_business findBusiness = new Find_business();
    findBusiness.setName(businessName);
    findBusiness.setAuthInfo(authToken.getAuthInfo());
    BusinessList businessList = inquiryPort.find_business(findBusiness);
    BusinessInfos businessInfos = businessList.getBusinessInfos();
    if (businessInfos == null || businessInfos.getBusinessInfo().length == 0) {
    System.out.println("Inquiry failed.");
    }else{
    System.out.println("Inquiry succeeded.");
    } 
    

其中获取 authentication token 的方法可以参考上述代码中的第四步,使用 authentication token 只需要在 Find_xxx 和 Save_xxx API 中设置相应的属性,可以参考第 5 步和第 6 步。如果使用 authentication token 访问 UDDI,用户可以对 UDDI 中所有的内容进行查询操作,但是 update/delete 操作只能作用于该用户自己创建的内容。

用户信息是否正确是获取 authentication token 的关键,IBM UDDI 使用下面列出的三处用户信息,并结合上述的配置选项来判断是否给用户提供合法的 authentication token。

  • Get_authToken API 中设置的用户信息
  • UDDI publisher 列表
  • UDDI 默认用户

如果用户同时选择“use authInfo credentials if provided”和 “automatically register UDDI publishers”, 表示使用 authentication token 中的信息,而且如果 authentication token 中包含的用户信息不在 UDDI 的 publisher 列表里面,系统会自动创建一个相应的 UDDI publisher。所以在这种情况下,Get_authToken 操作都会返回一个合法的包含指定用户信息的 authentication token。

如果用户只选择了“use authInfo credentials if provided”, 表示只使用 authentication token 中的信息,而不自动为用户创建 UDDI publisher,所以,只有当 authentication token 中包含的用户信息在 UDDI publisher 列表里面时,才能返回正确的 authentication token。否则返回 10150 错误。

如果用户只选择了“automatically register UDDI publishers”或者两个都不选,表示不使用 authentication token 中所包含的用户信息,UDDI 将使用默认用户来创建 authentication token。所以,不管用户在 Get_authToken API 中设置的是什么值,系统都会返回一个包含默认用户信息的 authentication token。

回页首

访问同时开启 UDDI 安全和平台安全的 UDDI

如果用户在使用 IBM UDDI 的时候,同时打开平台安全和 UDDI 安全 , 那么需要按照下面的方式设置平台安全的信息 (inquiry/publish port 中的 username 和 password 以及 SSL 属性 ):

((Stub) publishPort)._setProperty(Stub.USERNAME_PROPERTY, userName);
((Stub) publishPort)._setProperty(Stub.PASSWORD_PROPERTY, password);
((Stub) inquiryPort)._setProperty(Stub.USERNAME_PROPERTY, userName);
((Stub) inquiryPort)._setProperty(Stub.PASSWORD_PROPERTY, password);
((Stub) securityPort)._setProperty(Stub.USERNAME_PROPERTY, userName);
((Stub) securityPort)._setProperty(Stub.PASSWORD_PROPERTY, password);
System.setProperty("javax.net.ssl.trustStore", trustStore);
System.setProperty("javax.net.ssl.trustStorePassword", trustStorePassword);
System.setProperty("javax.net.ssl.keyStore", keyStore);
System.setProperty("javax.net.ssl.keyStorePassword", keyStorePassword);

将 authentication token 信息设置到 Save_xxx 和 Find_xxx API 中 :

saveBusiness.setAuthInfo(authToken.getAuthInfo());
findBusiness.setAuthInfo(authToken.getAuthInfo());

注意 :

如果用户不是一个注册的 UDDI publisher,这时需要选择“automatically register UDDI publishers”才能向 UDDI 中发布内容,否则返回 10150 错误。

回页首

访问未开启安全的 UDDI

当 UDDI 没有打开安全,用户可以通过以下方式向 UDDI 发布或查询内容:

  1. 获取 ServiceFactory UDDI_Service
    ServiceFactory factory = ServiceFactory.newInstance();
    UDDI_ServiceuddiService =(UDDI_Service)factory.loadService(UDDI_Service.class);
    
  2. 获取 UDDI_Publication_PortTypeUDDI_Inquiry_PortType
    UDDI_Publication_PortType publishPort = uddiService.getUDDI_Publication_Port();
    UDDI_Inquiry_PortType inquiryPort = uddiService.getUDDI_Inquiry_Port();
    
  3. 设置 publish URL 和 inquiry URL。
    ((Stub) publishPort)._setProperty(Stub.ENDPOINT_ADDRESS_PROPERTY, publishURL);
    ((Stub) inquiryPort)._setProperty(Stub.ENDPOINT_ADDRESS_PROPERTY, inquiryURL); 
    
  4. 向 UDDI 中发布内容 .
    Name businessName[] = new Name[1];
    businessName[0] = new Name();
    businessName[0].set_value("BusinessEntity");
    BusinessEntity newBusinesses[] = new BusinessEntity[1];
    newBusinesses[0] = new BusinessEntity();
    newBusinesses[0].setName(businessName);
    Save_business saveBusiness = new Save_business();
    saveBusiness.setBusinessEntity(newBusinesses);
    BusinessDetail businessDetail = publishPort.save_business(saveBusiness);
    URI businessKey = businessDetail.getBusinessEntity(0).getBusinessKey();
    if (businessKey == null) {
    System.out.println("Publish failed.");
    }else{
    System.out.println("Publish succeeded.");
    } 
    
  5. 从 UDDI 中查寻内容 .
    businessName[0] = new Name();
    businessName[0].set_value("BusinessEntity");
    Find_business findBusiness = new Find_business();
    findBusiness.setName(businessName);
    BusinessList businessList = inquiryPort.find_business(findBusiness);
    BusinessInfos businessInfos = businessList.getBusinessInfos();
    if (businessInfos == null || businessInfos.getBusinessInfo().length == 0) {
    System.out.println("Inquiry failed.");
    }else{
    System.out.println("Inquiry succeeded.");
    } 
    

    注意 : UDDI publish API 会使用默认的用户作为 UDDI entity owner ,默认用户可以在 WebSphere application server 控制台中的 UDDI>UDDI nodes>UDDI Node ID>Default user name 下设置。

回页首

IBM vs 其它 UDDI

总的来说,当用户需要连接其它厂商的 UDDI 服务器(非 IBM UDDI), 用户同样可以利用文章前面提到到两种安全机制:平台安全机制和 UDDI 安全机制来构建安全的 UDDI 应用。

IBM UDDI 与其它厂商的 UDDI 相比,有两点不同的特征:

  • 如果用户使用平台安全机制,用户就不需要设置 authentication token。也就是说,如果 IBM UDDI 服务器需要客户端请求指定 authentication token,用户只需要在 UDDI 传输端口 , 例如 UDDI_Publication_PortType, UDDI_Inquiry_PortType 上设置用户 / 密码信息就可以了。
((Stub) publishPort)._setProperty(Stub.USERNAME_PROPERTY, user);
((Stub) publishPort)._setProperty(Stub.PASSWORD_PROPERTY, password); 

而不需要如下的设置:

saveBusiness.setAuthInfo(authToken.getAuthInfo()); 

而像其它厂商的 UDDI 服务器,例如 SAP UDDI, 用户就需要根据 UDDI 服务器上的安全设置分别明确地在 UDDI API 上指定 SSL 和 authentication token 信息。

  • 对于 IBM UDDI, 用户不需要在 authentication token 中设置密码信息。但是对于其它厂商的 UDDI 服务器,例如 SAP UDDI,用户就需要明确设置密码信息。
回页首

总结

UDkeyStorePassword 认证方式 authentication token 有不同的实现方式。本文主要讲述了 IBM UDDI 产品的安全认证方式,在此基础上介绍了其它厂商的安全认证方式。相信通过本文,读者能够对 UDDI 的安全认证方式有更深入的了解。

回页首

下载

描述 名字 大小 下载方法
样例代码 Udditest.zip 6.41KB HTTP
关于下载方法的信息

参考资料

学习
  • UDDI Spec V3:OASIS 发布的 UDDI 最新规范文档。
  • Websphere 应用服务器信息中心 :您可以在其中找到应用程序服务器的各种版本的文档。
  • SAP 测试 UDDI 服务器 :这是 SAP 提供的供开发者使用的 UUDI 实现。
  • 了解 Web 服务规范,第 3 部分:统一描述、发现和集成 (UDDI):本教程将说明统一描述、发现和集成 (UDDI) 的基本概念,并介绍如何使用 Java 应用程序访问它。
  • Web 服务编程技巧与窍门: 在 UDDI 注册中心为 Web 服务注册开发 UDDI Java 应用程序:本技巧建立了一个使用统一描述、发现和集成(Universal Description, Discovery, and Integration,UDDI)来注册应用程序级消费的 Web 服务实例。
  • 使用 UDDI V3 加速前进:本文着重讨论对多注册中心异构环境、安全性以及策略与实现相分离这些方面的支持,这些方面是把版本 3 与先前几个版本显著区别开来的关键功能。
  • IBM developerWorks SOA and Web services 专区 提供了大量的文章,以及关于如何开发 Web 服务应用程序的初级、中级和高级教程。
  • 使用 IBM SOA Sandbox 进行试验!通过 IBM SOA 进行实际的亲手实践来提高您的 SOA 技能。
  • IBM SOA 网站 提供 SOA 的概述,并介绍 IBM 是如何帮助您实现 SOA 的。
  • 了解关于 developerWorks 技术事件和网络广播 的最新消息。请特别关注以下 SOA 和 Web 服务技术讲座:
    • Building SOA solutions and managing the service lifecycle
    • SCA/SDO: To drive the next generation of SOA
  • 访问 Safari 书店 ,浏览有关这些技术主题以及其他方面的书籍。

你可能感兴趣的:(api,IBM,Security,Authentication,token,websphere)