Web services 安全实践: 基于 HTTP Basic Authentication 为 Web services 配置传输层安全机制

转载:http://www.ibm.com/developerworks/cn/webservices/1106_webservicessecurity/

 

简介

正如"HTTP Basic Authentication"这个名字,它是 Authentication( 认证 ) 中最简单的方法。长期以来,这种认证方法被广泛的使用。当你通过 HTTP 协议去访问一个使用 Basic Authentication 保护的资源时,服务器通常会在 HTTP 请求的 Response 中加入一个"401 需要身份验证"的 Header,来通知客户提供用户凭证,以使用资源。如果你正在使用 Internet Explorer 或者 Mozilla Firefox 这样的可视化浏览器来访问需要认证的资源,浏览器会弹出一个窗口,让你输入用户名和密码,如果所输入的用户名在资源使用者的验证列表,并且密码完全正确,此时,用户才可以访问受限的资源。那么什么是 HTTP Basic Authentication 呢?如何在不同的服务器上配置 Basic Authentication 呢?下面本文将展开介绍。

 

HTTP Basic Authentication 介绍

HTTP BASIC 认证的基本流程如图 1 所示,

图 1. BASIC HTTP认证基本流程

图 1. BASIC HTTP认证基本流程

HTTP Basic Authentication 是指客户端在使用 HTTP 协议访问受限资源时,必须使用用户名和密码在一个指定的域 (Realm) 中获取认证。在正式开始之前,我们需要明白以下名词的含义:

  1. Authentication,即认证,验证。它是一种确认的过程,通过这样的认证过程,你可以确定某物体是不是它所声称的那种物体。这通常会涉及到用户名和密码,也可能是身份证明,或生物特征,如视网膜等。
  2. Realm,即域。一个 Realm 就是一系列用户名和密码的“数据库”,它通常用来保存、识别某个或某些 Web 应用中有效的用户和密码。它还定义了每个有效用户所对应的角色。

本文将介绍如何使用 HTTP BASIC Authentication 来保护 Web services endpoint 服务资源,当 Web services 的 Endpoints 被设置为 BASIC HTTP 认证才能访问的受限资源时,用户必须提供用户名密码才能使用它们,基本的流程如图 2 所示。

图 2. Web services 客户端访问受限 Web services 服务流程

图 2. Web services 客户端访问受限 Web services 服务流程

下面,本文将以 Tomcat 何 WebSphere Application Server 为例,分别讲述如何配置 Web services 的 endpoint 为受限资源,并使用 Web services 静态和动态客户端分别加以测试。

 

为 Tomcat 配置 Basic Authentication

本节将详细讲述如何在 Tomcat 下使用 Basic Authentication 来增强 Axis 实现的 Web services 访问的安全性。本文使用 Eclipse 来开发相关的例子,在这里假设您已经安装了相关的环境。

创建 Web services Provider 应用

在 Eclipse 中新建一个 Dynamic Web Project,并将其命名为“TomcatAxis”如图 3 所示:

图 3. 创建动态 WEB 工程

图 3. 创建动态 WEB 工程

该工程的目录结构如图 4 所示:

图 4. 工程结构

图 4. 工程结构

为 Web services 添加实现

创建一个基于 Axis 实现的 Web Service,本文采取“Bottom up Java bean Web Service”方式创建,其具体操作过程为:

  1. 创建该 Web services 的实现类,代码如下
    清单 1. Web services Provider 实现代码
     package sample.test; 
     public class ServiceImpl { 
      /** 
       * return the summation of the two integer arguments 
       * @param addend 
       * @param augend 
       * @return 
       */ 
      public int sum(int addend, int augend) { 
        return addend + augend; 
      } 
     }
  2. 基于该实现类,创建 Web Service,如图 5 所示
    图 5. 创建 Web Service
    图 5. 创建 Web Service

    完成上述步骤后,会在 /TomcatAxis/WebContent/wsdl/ 目录下创建一个名称为“ServiceImpl.wsdl”的 WSDL 文件。

  3. 将 Web Application 部署到 Tomcat 上,使用 Eclipse 自带的 Web services 测试工具“Web services Explorer”来测试所创建的 Web services 是否能被使用,如图 6 所示
图 6. 测试所创建的 Web services

图 6. 测试所创建的 Web services

在确认所创建的 Web services 能够正常使用后,需要为 Web Application 配置 Basic Authentication。

为 Web Application 配置 Basic Authentication:

  1. 打开 Tomcat 安装目录下的“conf”文件夹,修改文件“tomcat-users.xml”,该文件是用来存储 Tomcat 预加载的用户和角色定义的,此文件即是上文提到的 Realm。在“<tomcat-users>”中加入如下用户和角色:
    清单 2. 定义用户及其角色
      <!-- Web services invoker role --> 
      <role rolename="WsInvokerRole"/> 
      
      <!-- Web services invokers/users --> 
      <user username="wsaxis" password="wsaxis" roles="WsInvokerRole"/>
  2. 打开 Web 应用“TomcatAxis”的部署描述符:web.xml 文件,并在“<web-app>”中加入如下片段:
    清单 3. 配置安全资源
      <!-- configurations for BASIC Authentication --> 
      <security-constraint> 
        <web-resource-collection> 
          <web-resource-name>All Web services Endpoints</web-resource-name> 
          <url-pattern>/services/*</url-pattern> 
        </web-resource-collection> 
        
        <auth-constraint> 
          <description>Web services invokers are allowed doing invocation</description> 
          <role-name>WsInvokerRole</role-name> 
        </auth-constraint> 
      </security-constraint> 
      
      <!-- authentication method --> 
      <login-config> 
        <auth-method>BASIC</auth-method> 
        <realm-name>Realm of Web services Invokers</realm-name> 
      </login-config>

    在“<security-constraint>”片段内,定义了改 Web Application 需要保护的资源,可以通过“<url-pattern>”来定义符合一定 URL 样式的资源,上述片段的定义,保护了所有 Web services 的 endpoints。

    “<login-config>”片段定义了采取 BASIC 认证方式,其中“<realm-name>”只在 BASIC 认证方式下有效,它分配安全领域名,此名称供浏览器用于对话框标题,且为 Authorization 头部的一部分。

  3. 重启 Tomcat,骤重新测试该 Web Service,将有如图 7 提示框,提示输入用户名和密码:输入之前所定义的 wsaxis 用户名及其密码后,点击 OK,Web services 将会被调用。否则将无法正常调用到 Web Service。
    图 7. 信息输入对话框
    图 7. 信息输入对话框
 

测试 Tomcat 下 Basic Authentication

通常 Web services 可以有两种调用方式,即静态调用方式和动态调用方式。下面将分别介绍如何使用这两种方式验证 Basic Authentication 是否正常工作。

静态调用方式测试

首先,新建一个 Java Project,命名为“TomcatAxisClient”, 如图 8

图 8. 创建 Web services 测试客户端工程

图 8. 创建 Web services 测试客户端工程

其次,将前文所声称的 Web services 的 WSDL 的 URL 作为参数,生成 Web services 客户端,如图 9

图 9. 生成 Web services Client

图 9. 生成 Web services Client

完成上述操作后,将有如下结构的 Web services 客户端类生成,如图 10 所示:

图 10. 生成结果

图 10. 生成结果

使用上述客户端类,就可以实现 Web services 的调用。现在,需要创建一个测试类,实例化客户端类,调用 Web Service。类名为“sample.test.client.runable.StaticClientTest”,详细代码见清单 4.

清单 4. 静态调用类
 package sample.test.client.runable; 

 import java.net.URL; 
 import sample.test.ServiceImplServiceLocator; 
 import sample.test.ServiceImplSoapBindingStub; 

 public class StaticClientTest { 
  public static void main(String[] args) { 
    try { 
    // String userName = "wsaxis", password = "wsaxis"; 
      int addend = 64, augend = 128; 
      ServiceImplSoapBindingStub sisbs = new ServiceImplSoapBindingStub( 
          new URL(  "http://localhost:8080/TomcatAxis/services/ServiceImpl"), 
          new ServiceImplServiceLocator()); 
    // sisbs.setUsername(userName);   // sisbs.setPassword(password); 
      System.out 
          .println("Static Client Invocation:\n\tThe summation is: "
              + sisbs.sum(addend, augend)); 
    } catch (Exception e) { 
      e.printStackTrace(); 
    } 
  } 
 }

运行上述代码,你将发现 Web services 不能够被顺利调用,此处将会抛出 Web services 调用异常,如图 11 所示:

图 11. 未认证时执行结果

图 11. 未认证时执行结果

这个错误表明,你所调用的资源是受保护的,你必须提供相关的认证信息来访问它们。如果把如下代码的注释符去掉,

// String userName = "wsaxis", password = "wsaxis";
… … 
// sisbs.setUsername(userName);
 // sisbs.setPassword(password);

再重新编译,运行,你就能得到正确的结果,如图 12

图 12. 认证后执行结果

图 12. 认证后执行结果

由于 Web services 的 endpoint 被列为受限资源,需要使用这些资源,必须提供相应的认证信息。清单 4 中被注释掉的内容,正是用来向服务器认证时使用的,由于服务器无法获得认证信息,就返回了 401 Unauthorized 错误。去掉注释后的请求得到了服务器的认证,因而能够得到正确的结果。

动态调用方式测试

动态调用方式不需要生成 Web services 客户端,通过查找 Web services 提供的服务,就能调用 Web Service,此处不对动态调用方式详加解释, 清单 5 是使用动态调用的方式测试 Basic Authentication 的。

清单 5. 动态调用测试代码
 package sample.test.client.runable; 
 import javax.xml.namespace.QName; 
 import javax.xml.rpc.Call; 
 import javax.xml.rpc.ParameterMode; 
 import javax.xml.rpc.Service; 
 import javax.xml.rpc.ServiceFactory; 
 public class DynamicClientTest { 
  public static void main(String[] args) { 
    try { 
      String address = "http://localhost:8080/TomcatAxis/services/ServiceImpl"; 
      String namespaceURI = "http://test.sample"; 
      String serviceName = "ServiceImplService"; 
      String portName = "ServiceImpl"; 
      String operationName = "sum"; 
      String userName = "wsaxis", password = "wsaxis"; 
      int addend = 64, augend = 128; 
      ServiceFactory factory = ServiceFactory.newInstance(); 
      Service service = factory.createService(new QName(serviceName)); 
      Call call = service.createCall(new QName(portName)); 
      call.setTargetEndpointAddress(address); 
      QName intQName = new QName("http://www.w3.org/2001/XMLSchema","int"); 
      call.setOperationName(new QName(namespaceURI, operationName)); 
      call.addParameter("addend", intQName, ParameterMode.IN); 
      call.addParameter("augend", intQName, ParameterMode.IN); 
      call.setReturnType(intQName); 
      call.setProperty(Call.USERNAME_PROPERTY, userName); 
      call.setProperty(Call.PASSWORD_PROPERTY, password); 
      Object[] inParams = new Object[2]; 
      inParams[0] = new Integer(addend); 
      inParams[1] = new Integer(augend); 
      int value = ((Integer) call.invoke(inParams)).intValue(); 
      System.out.println("Dynamic Client Invocation:\n\tThe summation is: " + value); 
    } catch (Exception e) { 
      e.printStackTrace(); 
    } 
  } 
 }

需要指出的是,与静态调用方式不同,动态调用方式设置认证的用户名和密码是通过 Property(属性)来设置的(代码中加粗的部分)。上述代码的运行结果如图 13 所示:

图 13. 动态调用测试结果

图 13. 动态调用测试结果

如果去掉清单 4 中加粗的部分,同样服务器将返回 401 Unauthorized 错误。

下面,本文将结合 Rational Application Developer Standard Edition Version 8.0 和 WebSphere Application Server Version 7.0 来介绍如何在 WAS 上配置 HTTP Basic Authentication,并使用 JAX-WS 实现的 Web services 加以测试。

 

WAS 下配置 HTTP Basic Authentication

使用 RAD 开发 Web services Provider 应用

首先,如同第 3 节中所述,在 Rational Application Developer(以下简称 RAD)中创建一个 Dynamic Project,此处需要注意,由于 RAD 中所使用的 WAS 只能部署 Enterprise Application Archive(EAR),因此,需要创建相应的 EAR 工程,并把所创建的 Dynamic Web Project 座位该 EAR 的模块。如图 14 所示:

图 14. 创建动态 WEB 工程

图 14. 创建动态 WEB 工程

等待工程创建完毕之后,将有如图 15 所示的目录结构:图中高亮的两个工程是上述步骤所创建的。

图 15. 工程结构

图 15. 工程结构

接下来,我们仍然采用“Bottom up Java bean Web Service”方式创建用于测试的 Web Service:

  1. 创建 Web services 的实现类,并将如下代码复制并覆盖所创建的文件,如清单 6。
    清单 6. Web services Provider 实现代码
     package sample.test.jaxws; 
    
     public class JaxWsServiceImpl { 
      /** 
       * return the summation of the two integer arguments 
       * 
       * @param addend 
       * @param augend 
       * @return 
       */ 
      public int sum(int addend, int augend) { 
        return addend + augend; 
      } 
     }
  2. 使用该文件,创建 Web Service,在创建过程中,需要指定所采用的 Web services 运行时为“IBM WebSphere JAX-WS”,如图 16 所示
    图 16. 创建 Web services Provider
    图 16. 创建 Web services Provider
  3. Web services 创建完毕后,将会被自动发布到 WAS 上,使用 Web services Explorer 加以简单测试,以便检查 Web services 是否能够被访问调用等。

配置 Web services Provider 应用的受限访问资源

此处,我们需要仿照上文为 Web services Provider 应用配置安全性,将 Web services 的 endpoint 作为受限资源,定义在应用的部署描述符(web.xml)中。

  1. 打开 web.xml 文件,切换到 Design 页面,如图 17 所示
    图 17. web.xml 编辑页面
    图 17. web.xml 编辑页面
  2. 点击“Add …”按钮,在弹出的窗口中选择“Security Role”,确认后,对“Role Name”和“Description”赋值,其中“Role Name”是必填项,如图 18 所示
    图 18. 添加安全角色
    图 18. 添加安全角色
  3. 仿照步骤 2,添加“Security Constraint”项,展开“Authorization Constant”,点击“Add”按钮,添加一个 Role,名称为之前所创建的 Role:“wsRole”,继续配置 Security Constraint,将 Web services 的 endpoint 加入到受限资源中。配置完成后,如图 19 和图 20 所示:
    图 19. 添加受限资源
    图 19. 添加受限资源
    图 20. 添加受限资源 2
    图 20. 添加受限资源 2
  4. 仿照步骤 2,添加“Login Configuration”,在“Authentication Method”中输入“BASIC”,如图 21 所示
    图 21. 配置认证方式
    图 21. 配置认证方式

至此,Web services Provider 的受限资源以及应用的 Basic Authentication 都配置完毕。如果需要 Basic Authentication 起作用,还必须启用 WAS 的安全设置,下面我们将简要讲述如何启动 WAS 安全。

配置 WAS 安全

  1. 打开到 WAS 的控制台,如图 22 所示
    图 22. WAS 控制台
    图 22. WAS 控制台
  2. 登录后,选择“Security – Global Security”菜单,并点击“Security Configuration Wizard”按钮,如图 23 所示
    图 23. 配置 WAS 安全 1
    图 23. 配置 WAS 安全 1
  3. 在 Wizard 的步骤 2 中,选择“Federated repositories”作为资源库。点击“Next”,输入用户名密码,并确认密码,如图 24 所示。其中,用户名和密码将作为登录控制台的用户名和密码,此处,所输入的用户名和密码都是“jaxws”。完成向导后,保存所做的修改,并重新启动 WAS。
    图 24. 配置 WAS 安全 2
    图 24. 配置 WAS 安全 2
  4. 重新登录控制台,此时,将提示你输入用户名和密码,如图 25 所示:
    图 25. 配置 WAS 安全 3
    图 25. 配置 WAS 安全 3

部署 Web services Provider 应用

在启用了安全的 WAS 上部署步骤创建的 Web services Provider 应用。

首先,在 RAD 中,将所创建的工程导出为 EAR 包;

其次,部署所导出的 EAR 到 WAS 中,具体步骤如下:

  1. 登录 WAS 控制台,并打开“Applications - Application Types - WebSphere enterprise applications”;
  2. 点击“Install”按钮,在“Preparing for the application installation”页面,点击“Browse”按钮,浏览到已经导出的 EAR 文件,并单击“Next”,如图 26 所示
    图 26. 部署 Web services Provider 到 WAS 1
    图 26. 部署 Web services Provider 到 WAS 1
  3. 在新页面中选择“Detailed”选项,如图 27,单击“Next”
    图 27. 部署 Web services Provider 到 WAS 2
    图 27. 部署 Web services Provider 到 WAS 2
  4. 单击链接“Step 8”,在 RAD 中所创建的 Role 和 WAS 中用户或组之间建立关联,如图 28 所示:
    图 28. 建立角色 ( 用户 ) 关联
    图 28. 建立角色 ( 用户 ) 关联
  5. 完成向导,并启动该 Web services Provider,如图 29 所示:
    图 29. 启动 Web services Provider 应用
    图 29. 启动 Web services Provider 应用

至此,JAX-WS Web services Provider 的 Basic Authentication 已经配置完毕,下一节,将将输入和采用静态和动态调用方式测试它。

 

测试 WAS 下 Basic Authentication

静态调用方式测试

如同测试 Tomcat 上的 Basic Authentication 类似,需要在 RAD 中创建一个 Java Project,利用之前所创建的 Web services Provider 提供的 WSDL 文件,创建 Web services Client,需要指出的是,Web services 的运行时需要指定为“IBM WebSphere JAX-WS”。生成客户端之后的 Java Project 的目录结构如图 30 所示

图 30. 创建测试工程

图 30. 创建测试工程

创建一个测试 Class,命名为“sample.test.jaxws.client.runable.StaticClientTest”,其内容如清单 7 所示:

清单 7. 静态测试代码
 package sample.test.jaxws.client.runable; 
 import javax.xml.ws.BindingProvider; 
 import sample.test.jaxws.JaxWsServiceImplPortProxy; 

 public class StaticClientTest { 
  public static void main(String[] args) { 
    String userName = "jaxws", password = "jaxws"; 
    JaxWsServiceImplPortProxy proxy = new JaxWsServiceImplPortProxy(); 
    BindingProvider bp = (BindingProvider) proxy._getDescriptor() 
        .getProxy(); 
    bp.getRequestContext().put(BindingProvider.USERNAME_PROPERTY, userName); 
    bp.getRequestContext().put(BindingProvider.PASSWORD_PROPERTY, 
        password); 
    System.out.println(proxy.sum(123, 312)); 
  } 
 }

运行该测试 Class,将得到如图 31 所示的结果:

图 31. 测试结果

图 31. 测试结果

如果将“userName”或“password”赋予了其他的值,运行测试 Class,将得到 401 Unauthorized 错误,如图 32 所示:

图 32. 未加认证的测试结果

图 32. 未加认证的测试结果

动态调用方式测试

使用动态调用方式测试该 Web Service,需要基于 JAX-WS 的 API 开发客户端代码,本文给出测试需要 BASIC Authentication 认证的 Web services 的样例代码,如清单 8 所示:

清单 8. 动态测试代码

点击查看代码清单

以下是该样例代码的执行结果,如图 33 所示

图 33. 动态测试结果

图 33. 动态测试结果

通常,如果我们可以使用 Eclipse 或者 RAD 自带的 Web services Explorer 等测试工具来对 Web services 做简单的测试,或者,我们通过客户端来测试所开发的 Web services Provider。这样的测试通常只能发现简单而明显的问题,如何对 Web services Provider 做系统的测试呢? soapUI 这个工具能帮我们更加方便,更加系统地测试 Web services Provider。下面,我们将概述如何使用 soapUI 来测试 Web services 的 BASIC Authentication。

 

使用 SOAPUI 测试配置了 Basic Authentication 的 Web Service

soapUI 的是世界领先的 SOA 和 Web services 的测试工具。凭借其易于使用的图形界面和企业级功能,soapUI 能让你轻松,快速的创建和执行自动化测试,回归和负载测试。

首先,需要从 soapUI 的 官方网站 下载最新的 soapUI 安装文件,安装 soapUI。

其次,创建一个 soapUI 测试工程,提供被测试 Web services 的 WSDL 以便创建测试用例。如图 34 所示

图 34. soapUI 新建工程

图 34. soapUI 新建工程

如果选择了“Create Test Suite”,soapUI 将根据 Web services 的 operation 创建测试用例,同时,你还可以创建相关的性能测试用例,如图 35 所示

图 35. 生成测试集合

图 35. 生成测试集合

图 36 给出了所创建的测试工程,打开测试用例,可以看出,屏幕被分割成 3 个区域,在区域 A 中,显示了所创建的功能性测试用例和用于测试 Web services 性能的 Load Test 用例。区域 B 是 Web services 请求的配置区域,此处可以设置 Web services 使用的参数,认证等相关的信息。B 区中,红方格中的 Username 和 Password 正式设置 BASIC Authentication 使用的用户名和密码的。区域 C 是 Web services 请求返回(Response)显示区域。

图 36. soapUI 布局

图 36. soapUI 布局

然后,在区域 B 中,给 Web services 所使用参数赋值,并点击 B 区上方的“botton ”按钮,如图 37 所示。

图 37. 运行测试

图 37. 运行测试

此时,由于没有设置相关的认证信息,将会得到图 38 所示的相关错误信息。

图 38. 未认证时 soapUI 测试结果

图 38. 未认证时 soapUI 测试结果

在 B 区域红方格所示区域中输入认证信息,再重新执行测试用例,将得到如图 39 所示的结果。

图 39. soapUI 添加认证信息

图 39. soapUI 添加认证信息

以上就是如何使用 soapUI 来测试 Web services BASIC Authentication 的步骤,从中我们可以发现,只需要简单的操作便可以实现 Web services 的测试,因此,soapUI 对于提供 Web services 的测试效率是有帮助的。

posted @ 2014-02-20 17:49  仅存的记忆  阅读(934)  评论(0编辑  收藏  举报