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

日期: 2008-06-22 作者:赵一三朱朴王越 来源:TechTarget中国

  本文主要介绍了 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 用户与用户角色对应关系
 
  数据保密


  数据保密保证了在网络传输层的数据安全性。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
 
  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 的平台安全打开后,用户可以在 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 发布或查询内容时,可以通过以下方式:


  获取 ServiceFactory 和 UDDI_Service。 ServiceFactory factory = ServiceFactory.newInstance();
  UDDI_ServiceuddiService =(UDDI_Service)factory.loadService(UDDI_Service.class);
 
  获取 UDDI_Publication_PortType 和 UDDI_Inquiry_PortType。   UDDI_Publication_PortType publishPort =   uddiService.getUDDI_Publication_Port();
  UDDI_Inquiry_PortType inquiryPort =   uddiService.getUDDI_Inquiry_Port();
 
  设置 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);
 
  向 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.”);
  }
 
  从 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.”);
  }
 
  注意 :


  关于 V3SOAP_Inquiry_User_Role 的设置 :


  如果“EveryOne”和“All authenticated”都没有被选中会出现错误“(403) Forbidden”。


  如果“EveryOne”被选中,所有的用户都可以从 UDDI 中查寻内容,这时并不需要向 inquiry port 设置用户名和密码。


  如果“All authenticated”被选中,只有被授权的用户才有权限从 UDDI 中查寻内容,这时必须向 inquiry port 设置用户名和密码。如果使用非授权的用户查询会出现错误“(401) Unauthorized”。 


  关于 V3SOAP_Publish_User_Role 的设置 :


  如果“EveryOne”和“All authenticated”都没有被选中 , 错误“(403) Forbidden”会出现。


  如果“EveryOne”被选中会出现 UDDI 错误 10120。


  如果“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 中查询和发布内容:


  获取 ServiceFactory 和 UDDI_Service。 ServiceFactory factory = ServiceFactory.newInstance();
  UDDI_ServiceuddiService =(UDDI_Service)factory.loadService(UDDI_Service.class);
 
  获取 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();
 
  设置 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);
 
  获取 authentication token。 Get_authToken getAuthToken = new Get_authToken();
  getAuthToken.setUserID(userName);
  getAuthToken.setCred(password);
  AuthToken authToken = null;
  authToken = securityPort.get_authToken(getAuthToken);
 
  使用 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.”);
  }
 
  使用 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 发布或查询内容:
 
  获取 ServiceFactory 和 UDDI_Service。 ServiceFactory factory = ServiceFactory.newInstance();
  UDDI_ServiceuddiService =(UDDI_Service)factory.loadService(UDDI_Service.class);
 
  获取 UDDI_Publication_PortType 和 UDDI_Inquiry_PortType。   UDDI_Publication_PortType publishPort = uddiService.getUDDI_Publication_Port();
  UDDI_Inquiry_PortType inquiryPort = uddiService.getUDDI_Inquiry_Port();
 
  设置 publish URL 和 inquiry URL。 ((Stub)   publishPort)._setProperty(Stub.ENDPOINT_ADDRESS_PROPERTY, publishURL);
  ((Stub) inquiryPort)._setProperty(Stub.ENDPOINT_ADDRESS_PROPERTY, inquiryURL);
 
  向 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.”);
  }
 
  从 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 的安全认证方式有更深入的了解。


  作者简介
  
  赵一三2003年加入 IBM,在 Lotus 从事开发与测试的工作。2006年加入 IBM SOA Design Center,他是 China SDC 的代表。你可以通过以下方式与他联系:zhaoyis@cn.ibm.com 。
 
  朱朴是 IBM SOA Design Center 的一名工程师,你可以通过以下方式与他联系:zhupu@cn.ibm.com。
 
  王越是 IBM SOA Design Center 的一名工程师,你可以通过以下方式与她联系:ywangwy@cn.ibm.com。

我们一直都在努力坚持原创.......请不要一声不吭,就悄悄拿走。

我原创,你原创,我们的内容世界才会更加精彩!

【所有原创内容版权均属TechTarget,欢迎大家转发分享。但未经授权,严禁任何媒体(平面媒体、网络媒体、自媒体等)以及微信公众号复制、转载、摘编或以其他方式进行使用。】

微信公众号

TechTarget微信公众号二维码

TechTarget

官方微博

TechTarget中国官方微博二维码

TechTarget中国

相关推荐

  • 数字化转型:如何更好地利用API和微服务

    API,即应用程序编程接口,它提供给应用程序、开发人员访问其它应用的能力,而又无需访问源码,无需理解内部工作机制细节;简单地说,API就是实现应用与应用连接的一种隐形的桥梁。

  • 金融行业数字转型:利用API构建新IT基础

    从制造业、物流业,银行业到零售业,各行各业的根基都因应用经济的兴起发生着深刻的变革。在互联网和智能手机普及化的推动下,这种现象变得司空见惯。到2021年 ,蓬勃发展的全球应用经济的预估总值将达到6.3万亿美元,相比2016年的1.3万亿美元,增长近5倍。

  • 如何使用Azure API管理服务?

    在云和微服务架构时代,API是数字化业务的通用语言。根据分析公司Forrester Research预测,仅在美国,API管理工具的支出将在未来5年内达到近30亿美元。

  • 私有存储云如何构建?

    如何构建自己的私有存储云呢?在这之前,我们要先退后一步,思考一下云计算到底意味着什么。