当前位置: 代码迷 >> Web前端 >> 利用 Geronimo 2.2 创设安全的 Web Service 应用
  详细解决方案

利用 Geronimo 2.2 创设安全的 Web Service 应用

热度:537   发布时间:2012-09-23 10:28:11.0
利用 Geronimo 2.2 创建安全的 Web Service 应用

简介: ?随着 Web Service 应用越来越广泛, 如何保证服务能够安全的访问和传输,也逐渐引起开发人员和用户的关注。Web Service 的安全可以从两方面考虑:访问安全和传输安全 .。前者主要指只有授权用户可以访问应用, 而后者侧重于在消息传输过程中如何保证消息的私密性和完整性。本文介绍了如何在 Apache Geronimo 开发和部署安全的 Web Service 应用,以确保信息交互的安全,将侧重介绍如何基于 HTTP/HTTPS 协议保护 Web Service 应用访问和传输的安全。

?

Web Service Security 简介

在 Java EE 平台上,先后有了 JAX-RPC 和 JAX-WS 两个 Web Service 应用规范,但是两者均未对安全方面做详细规定。那么如何确保 Web Service 应用的安全呢?总所周知,Web Service 应用的服务端和客户端是使用 SOAP 作为交互协议,而 SOAP 作为一个应用层的协议,可以基于多种其他协议传输, 例如 HTTP/HTTPS,FTP 等。 而在实际的应用环境之中, HTTP/HTTPS 协议是应用最为广泛的 .。事实上, 在 SOAP 和 Web Service 的相关规范中, 主要对 SOAP 基于 HTTP/HTTPS 上进行传输作了说明。显然,当我们考虑 Web Service 安全时, 在传输协议进行安全控制便是一个自然而然的选择方案之一。

Apache Geronimo 中的 Web Service Provider

Apache Geronimo 共集成了三个比较流行的 Web Service 引擎, 分别是 Apache Axis, Apache Axis2 和 Apache CXF。 对于 Axis, 通过集成其实现对 JAX-RPC 规范的支持, 后续两个项目, 侧重提供对 JAX-WS 规范的支持。 在 Geronimo 的两个发行版本 Geronimo-Tomcat 和 Geronimo-Jetty 中, 分别默认启用了 Axis2 和 CXF。对于 Geronimo 的两个发行版本,用户可以通过安装对应插件并进行简单配置以切换至另外一种 Web Service 引擎, 详情请参照 Geronimo 的相关文档,,本文不再作累述。 默认情况下, 本文示例均是运行于 Geronimo-Tomcat 发行版本上,并使用 Axis2 作为 Web Service 引擎,并遵循 JAX-WS 规范编写。

一个简单的 Web Service 应用

本文中, 我们以一个在线书店的应用为例, 其提供通过书名检阅图书的功能, 并以 Web Service 的形式对外提供服务。同时还有一个 Web 客户端应用,来访问在线书店提供的服务。如 清单 1 所示,服务端是一个简单的 POJO 类,并添加了 WebService 标识。其提供 queryByName 的方法,以传入的 name 为参数检索是否有符合条件的书籍,最终返回一个 Book 对象数组。


清单 1. 在线书店服务端实现

				
@WebService(name = "BookStore", targetNamespace = "http://geronimo.apache.org/bookstore") 
 public class BookStoreImpl { 

    private List<Book> books = new LinkedList<Book>(); 

    @PostConstruct 
    protected void initialize() { 
        books.add(new Book("1", "Thinking In Java", "Bruce")); 
        books.add(new Book("2", "WAS CE Bible", "WAS CE Team")); 
    } 

    public Book[] queryByName(String name) { 
        if (name == null || name.length() == 0) { 
            return new Book[0]; 
        } 
        List<Book> foundBookList = new ArrayList<Book>(); 
        for (Book book : books) { 
            if (book.getName().indexOf(name) != -1) { 
                foundBookList.add(book); 
            } 
        } 
        return foundBookList.toArray(new Book[0]); 
    } 

    @PreDestroy 
    protected void destory() { 
        books.clear(); 
    } 
 } 
       

?

同时,在部署文件 web.xml 中,我们将 清单 1 中所示 POJO 类以 Servlet 形式对外发布,具体配置请参照 清单 2 。


清单 2. web.xml 配置片段

				
 <servlet> 
 <servlet-name>BookStore</servlet-name> 
    <servlet-class> 
            org.apache.geronimo.samples.securityWebService.BookStoreImpl 
 </servlet-class> 
 </servlet> 
 <servlet-mapping> 
 <servlet-name>BookStore</servlet-name> 
    <url-pattern>/bookstore</url-pattern> 
 </servlet-mapping> 
       

?

将以上所示的应用部署至 Apache Geronimo 中后,在浏览器输入 http://localhost:8080/SecurityWebServices/bookstore 后,如若 图片 1 所示,即表示该在线书店的应用已经成功部署了。


图片 1. BookStoreImplService 访问页面
BookStoreImplService 访问页面

Web Service 客户端

客户端同样是一个 Web 应用程序,首先通过工具根据 Geronimo 生成的 WSDL 文件生成本地的相关类文件, 通过在 BookStoreClient 中使用 WebServiceRef 标识注入的方式获取 BookStore 服务的引用, 请参照 清单 3 :


清单 3. 客户端代码片段

				
				BookStoreClient.java
           
 @WebServiceRef(name = "services/BookStore") 
 private BookStoreImplService service; 

 protected void doPost(HttpServletRequest request, HttpServletResponse response) 
    throws ServletException, IOException { 
        String queryName = request.getParameter("name"); 
        if (queryName != null && queryName.length() > 0) { 
            request.setAttribute("books", 
                service.getPort(BookStore.class).queryByName(queryName)); 
        } 
        request.getRequestDispatcher("index.jsp").forward(request, response); 
 } 
       

?

而在客户端应用的 web.xml 和 geronimo-web.xml 文件中, 需要配置该服务的一些参数, 请参照 清单 4 。设置参数主要包括服务端 Web Service 的发布地址等信息,对应于 清单 2 中的配置。


清单 4. web.xml/geronimo-web.xml 配置片段

				
				web.xml

 <service-ref> 
        <service-ref-name>services/BookStore</service-ref-name> 
        <service-interface> 
            org.apache.geronimo.samples.securityWebService.BookStoreImplService 
        </service-interface> 
 </service-ref> 
 geronimo-web.xml

 <name:service-ref> 
 <name:service-ref-name>services/BookStore</name:service-ref-name> 
        	 <name:port> 
            <name:port-name>BookStorePort</name:port-name> 
            <name:protocol>http</name:protocol> 
            <name:host>localhost</name:host> 
            <name:port>8080</name:port> 
            <name:uri>/SecurityWebServices/bookstore</name:uri> 
        </name:port> 
 </name:service-ref> 
       

?

至此, 我们完成了一个简单的在线书库的例子。通过在浏览器输入 http://localhost:8080/SecurityWebServiceClient/,并以 Java 作为关键字检索书籍,将如 图片 2 所示。


图片 2. BookStoreClient 访问页面
BookStoreClient 访问页面

目前为止,示例中的 Web Service 应用没有任何安全设置,任何客户端均可以直接访问。 在后续的章节中,我们将基于该示例展示在 Apache Geronimo 中如何使用各种安全策略来确保 Web Service 应用的安全,包括授权访问和传输安全。

基于 HTTP BASIC 安全认证策略

HTTP BASIC 的认证方式非常简单,当客户端向服务端受保护资源发起请求时,服务端会返回的消息中包括这样一个消息头 WWW-Authenticate: Basic realm="example.com",此时如果客户端是浏览器,则一个输入框将弹出,提示用户输入用户名和密码。 在用户输入用户名和密码之后,客户端使用 Base64 编码方式对用户名和密码进行加密并返回至服务端。由于我们的 Web Service 应用实质上是通过一个 Servlet 的形式对外发布, 显而易见,我们可以通过在 web.xml 和 geronimo-web.xml 中为 Servlet 对应的访问路径进行安全设置, 由此可达到对该 Web Service 应用授权访问。 请参照 清单 5 和 清单 6 。


清单 5. web.xml 配置片段

				
 <security-constraint> 
 	 <web-resource-collection> 
            	 <web-resource-name>basicResources</web-resource-name> 
            	 <url-pattern>/bookstore/*</url-pattern> 
            	 <http-method>POST</http-method> 
            	 <http-method>GET</http-method> 
        	 </web-resource-collection> 
        	 <auth-constraint> 
       		 <role-name>admin</role-name> 
        	 </auth-constraint> 
        	 <user-data-constraint> 
         	 <transport-guarantee>NONE</transport-guarantee> 
        	 </user-data-constraint> 
    	 </security-constraint> 
    	 <login-config> 
        		 <auth-method>BASIC</auth-method> 
 <realm-name>geronimo-admin</realm-name> 
 </login-config> 
 <security-role> 
        <role-name>admin</role-name> 
 </security-role> 
       



清单 6. geronimo-web.xml 配置片段

				
 <web:security-realm-name>geronimo-admin</web:security-realm-name> 
 <sec:security> 
 <sec:role-mappings> 
    <sec:role role-name="admin"> 
        <sec:principal name="admin" 
          class="org.apache.geronimo.security.realm.providers.GeronimoGroupPrincipal" /> 
        </sec:role> 
    </sec:role-mappings> 
 </sec:security> 
       

?

在 清单 5 中设置了对访问路径 /bookstore 的任何 GET 和 POST 请求都需要使用 HTTP BASIC 认证方式,允许访问的角色为 admin。而在 清单 6 中, 指定了执行认证的安全域,出于示例方便。我们直接使用了 Geronimo 自带的 geronimo-admin 作为指定安全域,,用户完全可以定义和部署自己的安全域,同时将角色 admin 映射为安全域中的 admin 组,即当登录用户隶属于 admin 组时,其将具备对受保护资源的访问权限。 当重新部署之后, 此时再通过浏览器访问 http://localhost:8080/SecurityWebServices/bookstore?WSDL, 会提示输入用户名和密码。如 图片 3 所示。


图片 3. BookStoreImplService 访问页面
BookStoreImplService 访问页面

接下来,我们对 Web 客户端进行修改,使其可以访问受 HTTP BASIC 认证方式保护的 Web Service 应用。 在 JAX-WS 的 API 中, 可以通过 BindingProvider 接口来设置认证所需的用户名和密码。 请参照 清单 7 ,出于示例方便, 用户名和密码采取硬编码的方式, 实际使用时可以采取更灵活的方式。


清单 7. BookStoreClient 代码片段

				
 String queryName = request.getParameter("name"); 
 if (queryName != null && queryName.length() > 0) { 
    BookStore bookStore = service.getPort(BookStore.class); 
    BindingProvider bindingProvider = (BindingProvider) bookStore; 
    bindingProvider.getRequestContext().put(BindingProvider.USERNAME_PROPERTY, "system"); 
   bindingProvider.getRequestContext().put(BindingProvider.PASSWORD_PROPERTY,"manager"); 
    request.setAttribute("books", bookStore.queryByName(queryName)); 
 } 
 request.getRequestDispatcher("index.jsp").forward(request, response); 
       

?

通过在客户端代码中添加认证信息,我们的客户端又可以访问在线书店的 Web Service 应用了。从 清单 7 可 以注意到, 用户需要修改客户端代码以添加登录所需信息。 事实上, Apache Geronimo 在应用服务器平台级别提供了相关支持, 用户可以通过在部署文件中定义 Credential Store 和指定登录信息的方式, 由应用服务器来处理登录所需事宜。下面示例中, 我们仍然使用应用服务器自带的 geronimo-admin 安全域, 在实际开发和生成环境, 用户必需定义自己的安全域以及验证模块。 详细步骤如下 :

  • 停止 Apache Geronimo, 编辑 var/config/config.xml 文件, 添加如 清单 8 所示的配置信息, 并拷贝文章下载示例中的 simple_credentials.properties 文件到 var/security 目录。
  • 修改客户端应用程序的部署文件 geronimo-web.xml, 添加如 清单 9 所示的配置信息。
  • 删除 清单 7 中位于客户端 BookStoreClient 类中用于登录认证的相关代码。
  • 启动 Apache Geronimo 应用服务器, 并重新部署 SecurityWebServiceClient 应用程序。


清单 8. config.xml

				
 <module name="org.apache.geronimo.framework/server-security-config/2.2/car"> 
  <gbean name="org.apache.geronimo.framework/server-security-config/2.2/car? 
        ServiceModule=org.apache.geronimo.framework/server-security-config/2.2/car,
        j2eeType=LoginModule,name=simple-crddentials-login" 
        gbeanInfo="org.apache.geronimo.security.jaas.LoginModuleGBean"> 
        <attribute name="loginModuleClass"> 
            org.apache.geronimo.security.realm.providers. 
            GeronimoPropertiesFileMappedPasswordCredentialLoginModule 
        </attribute> 
        <attribute name="options"> 
            credentialsURI=var/security/simple_credentials.properties 
        </attribute> 
        <attribute name="loginDomainName">simple-crddentials</attribute> 
    </gbean> 
    <gbean name="org.apache.geronimo.framework/server-security-config/2.2/car? 
        ServiceModule=org.apache.geronimo.framework/server-security-config/2.2/car,
        j2eeType=LoginModuleUse,name=simple-crddentials-login-use" 
        gbeanInfo="org.apache.geronimo.security.jaas.JaasLoginModuleUse"> 
        <attribute name="controlFlag">REQUIRED</attribute> 
        <reference name="LoginModule"> 
            <pattern> 
                <name>simple-crddentials-login</name> 
            </pattern> 
        </reference> 
    </gbean> 
    <gbean name="org.apache.geronimo.framework/server-security-config/2.2/car? 
        ServiceModule=org.apache.geronimo.framework/server-security-config/2.2/car,
        j2eeType=LoginModuleUse,name=properties-login"> 
        <reference name="Next"> 
            <pattern> 
                <name>simple-crddentials-login-use</name> 
            </pattern> 
        </reference> 
    </gbean> 
 </module> 
       

?

在 清单 8 中,我们为当前服务器默认使用的安全域的登录链添加一个新的 LoginModule GeronimoPropertiesFileMappedPasswordCredentialLoginModule , 此模块的作用是当用户使用其所在的安全域进行认证时,会将在 simple-credentials.properties 配置文件中对应的用户名和密码信息对添加到 Subject 中 的 Private Credentials 中去。以属性文件中第一行的内容为例,system=system:system=manager,第一个 system 对应于当前登录所使用的用户名,第二个 system 为登录信息的名称,最后的 system 和 manager 则为真正使用的用户名密码信息。后续会介绍 Geronimo 如何使用保存在 Subject 中的 Private Credentials 信息为 Web Service 的访问提供平台级别支持。

?
清单 9. geronimo-web.xml 片段

				
 <name:service-ref> 
    <name:service-ref-name>services/BookStore</name:service-ref-name> 
        <name:port> 
            <name:port-name>BookStorePort</name:port-name> 
            <name:protocol>http</name:protocol> 
            <name:host>localhost</name:host> 
            <name:port>8080</name:port> 
            <name:uri>/SecurityWebServices/bookstore</name:uri> 
            <name:credentials-name>system</name:credentials-name> 
        </name:port> 
    </name:service-ref> 
 <web:security-realm-name>geronimo-admin</web:security-realm-name> 
    <app:security xsi:type="sec:securityType"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> 
        <sec:credential-store-ref> 
            <dep:name>SimpleCredentialStore</dep:name> 
        </sec:credential-store-ref> 
        <sec:default-subject> 
            <sec:realm>geronimo-admin</sec:realm> 
            <sec:id>system</sec:id> 
        </sec:default-subject> 
    </app:security> 
    <dep:gbean name="SimpleCredentialStore"
        class="org.apache.geronimo.security.credentialstore.SimpleCredentialStoreImpl"
        xsi:type="dep:gbeanType"> 
        <dep:xml-attribute name="credentialStore"> 
            <credential-store 
                xmlns="http://geronimo.apache.org/xml/ns/credentialstore-1.0"> 
                <realm name="geronimo-admin"> 
                    <subject> 
                        <id>system</id> 
                        <credential> 
                            <type> 
                                o.a.g.security.credentialstore.NameCallbackHandler 
                            </type> 
                            <value>system</value> 
                        </credential> 
                        <credential> 
                            <type> 
                                o.a.g.security.credentialstore.PasswordCallbackHandler 
                            </type> 
                            <value>manager</value> 
                        </credential> 
                    </subject> 
                </realm> 
            </credential-store> 
        </dep:xml-attribute> 
 </dep:gbean> 
       

?

清单 9 为 更新后的 Web Service 客户端的部署文件,相比于没有安全设置的配置,可以看出, service-ref 元素增加了一个子元素 credentials-name, 同时在安全配置中添加了 default-subject 和 credential-store-ref 两个元素。关于各项配置的含义,请参照 表格 1 :


表 1. 安全设置说明

元素位置及名称 配置值 配置说明
service-ref-name/port/credentials-name system 该名称对应于用户名密码对的名称
security/credential-store-ref/name SimpleCredentialStore 登录时使用的 Credential Store,主要包含了登录时所使用的 CallbackHandler 信息,当前配置值指向了后续的 SimpleCredentialStore GBean
security/default-subject/realm geronimo-admin 登录时使用的安全域
security/default-subject/id system 和上一行的 realm 值一起在 Credential Store 中定位到登录时所使用的 CallbackHandler 设置

那么 Geronimo 是如何通过以上配置来提供相关功能呢?具体步骤如下所示:

  • 用户请求到达 Web Service 客户端时,Geronimo 检查到当前会话没有安全信息,则使用 default-subject 配置信息,使用从 Credential Store 中获取的 CallbackHandler 信息对 geronimo-admin 安全域执行标准的 JAAS 登录操作。
  • 在对 geronimo-admin 安全域执行登录操作时,安全域登录链中包含的所有登录模块均被执行,在执行到 清单 8 中添加的 LoginModule 时,属性文件中以 system 为键值的所有登录信息均被添加到 Subject 的 Private Credential 中。
  • 当执行到客户端代码中关于访问远端 Web Service 的代码时,在用户请求发送之前,Geronimo 会以 credentials-name 的配置值 system 为键值在当前会话的 Subject 中检索对应的用户名和密码信息,并通过标准 JAX-WS 方法进行设置。

如此,通过 清单 8 中关于登录模块的配置和 清单 9 中关于 Default Subject 的配置,实现了在服务器级别的安全支持,而对于 Web Service 客户端程序而言,无需在其代码中添加安全认证的逻辑。事实上,正如第三步骤所描述,Geronimo 在后台执行的代码与 清单 7 一致,相关代码位于 JAX-WS 插件中 geronimo-jaxws 的 org.apache.geronimo.jaxws.client.PortMethodInterceptor 类中 , 感兴趣的读者可以结合阅读。

另外,如果远端请求的用户名和密码与登录到当前域的用户密码是一致的,如当前示例中,则可以使用 Geronimo 另外一个 LoginModule 的实现 org.apache.geronimo.jaas.NamedUPCredentialLoginModule,并指定 org.apache.geronimo.jaas.NamedUPCredentialLoginModule.Name 选项为 credentials-name 元素的值,也可以达到同样的效果。但相比较于 清单 8 中 所使用的 GeronimoPropertiesFileMappedPasswordCredentialLoginModule 来说,略欠缺灵活性,但是工作原理一致,即将远端 Web Service 登录所需信息以 Private Credential 的形式添加到当前会话的 Subject 中。

?

使用 SSL 确保消息传输的完整性和私密性

使用上述 HTTP BASIC 的认证方式,我们达到了 Web Service 应用授权访问的目的,但是登录成功之后,服务端和客户端之间交互的 SOAP 信息也是使用明文传输, 第三方完全可以通过截取网络传输包获取 SOAP 消息的内容。而通过 SSL, 可以最大程度上弥补这一缺陷,使得 Web Service 交互的安全性得到进一步的提高。

首先, 修改 Web Service 服务端的配置文件, 将 transport-guarantee 元素的值由原来的 NONE 改成 CONFIDENTIAL, 这样将对受保护资源将使用 SSL 连接方式。 如 清单 10 所示 :


清单 10. web.xml 配置片段

				
 <security-constraint> 
        <web-resource-collection> 
            <web-resource-name>basicResources</web-resource-name> 
            <url-pattern>/bookstore/*</url-pattern> 
            <http-method>POST</http-method> 
            <http-method>GET</http-method> 
        </web-resource-collection> 
        <auth-constraint> 
            <role-name>admin</role-name> 
        </auth-constraint> 
        <user-data-constraint> 
            <transport-guarantee>CONFIDENTIAL
</transport-guarantee> 
        </user-data-constraint> 
 </security-constraint> 
       

?

其次, 客户端访问时, 需要使用 HTTPS 协议和端口进行访问, 将 geronimo-web.xml 文件中的 service-ref 更新如清单 11 所示 :

?
清单 11. geronimo-web.xml

				
 <name:service-ref> 
        <name:service-ref-name>services/BookStore</name:service-ref-name> 
        <name:port> 
            <name:port-name>BookStorePort</name:port-name> 
            <name:protocol>https</name:protocol> 
            <name:host>localhost</name:host> 
            <name:port>8443</name:port> 
            <name:uri>/SecurityWebServices/bookstore</name:uri> 
            <name:credentials-name>system</name:credentials-name> 
       	 </name:port> 
 </name:service-ref>            
       

?

最后,关闭 Geronimo 服务器,在命令行执行 set GERONIMO_OPTS=-Djavax.net.ssl.trustStore=$YOUR_GERONIMO_HOME/var/security/keystores/geronimo-default -Djavax.net.ssl.trustStorePassword=secret, 并重新启动 Geronimo 服务器。此时 Web Service 客户端与服务端的交互, 将通过 HTTPS 进行传输 . 在设置 Trust Store 时, 可以依据实际环境使用其他方式, 比如将服务端的公钥导入 JRE 的默认 Trust Store。需要强调地是,本文示例中 Web Service 服务端和客户端使用的是同一个 Geronimo 实例,而 Geronimo 默认的 HTTPS Connector 使用的证书是 $YOUR_GERONIMO_HOME/var/security/keystores/geronimo-default, 所以设置 javax.net.ssl.trustStore 也指向同一位置。如果需要访问第三方发布并基于 HTTPS 协议传输的 Web Service 应用,则需要将其证书导入到本地的 Trust Store 中,并为以上两个参数设置合适的值。

基于 CLIENT CERT 的安全认证策略

在授权访问方面,除了基于用户名和密码的 HTTP BASIC 认证方式之外,CLIENT-CERT 也是一个比较好的选择。通常基于 HTTPS 的访问中,只需要服务端提供证书表明其身份,在之前的例子也介绍到,客户端需要将服务端的公共证书添加到本地受信密钥库中。而当使用 CLIENT-CERT 认证方式时,客户端也必需提供证书来表明自己的身份,换句话说,服务端和客户端均需要提供证书以表明各自身份。所以,CLIENT-CERT 是一种比较特殊的 SSL 使用方式。现实情况中,这种认证方式使用的不是很多,因为大多数用户并没有自己的证书,但在 B2B 场景中会见到其身影。例如两家公司之间可以使用该认证方式来确保信息交互的安全。

为示例方便,我们将使用两个 Geronimo 应用服务器实例,分别部署 Web Service 应用的服务端和客户端。为避免端口冲突,用户可以通过修改其中一台服务器实例的 var/config/config-substitutions.properties 文件中 PortOffset 的值为 10,使得两个服务器实例同时在一台机器上运行。实现步骤如下所示:

1. 使用 KeyTool 或者其他工具为 Web Service 客户端生产密钥库文件 client.jks,并导出客户端证书,再将其导入服务端受信的密钥库文件 trustedclient.jks 中。

2. 在 Web Service 服务端所在的应用服务器,通过控制台中 Web Server 配置页面,添加支持 CLIENT-CERT 方式的 HTTPS Connector。填写配置时,需要注意的是以下配置项:


表 2. CLIENT-CERT HTTPS Connector 关键配置项

属性名称 配置值 属性说明
keystoreFile ../security/keystores/geronimo-admin 服务端 HTTPS Connector 使用的密钥库文件位置
port 8444 服务端 HTTPS Connector 监听端口
clientAuth true 是否支持 CLIENT-CERT 认证方式
keyAlias 密钥库中服务端所使用证书的别名,如果不设置,则为密钥库中读取的第一个密钥
keystorePass secret 用于访问密钥库文件的密码
truststoreFile ../security/keystores/trustedclient.jks 用户验证客户端证书的密钥库文件位置
truststorePass secert 访问受信任客户端密钥库文件的密码

3. 修改 Web Service 服务端部署文件,如 清单 12 所示:


清单 12. 使用 CLIENT-CERT 认证方式的 Web Service 服务端部署文件 geronimo-web.xml 片段

				
 <web:security-realm-name>client-cert-realm</web:security-realm-name> 
 <sec:security> 
    <sec:credential-store-ref> 
        <dep:name>client-cert-credential-store</dep:name>            
    </sec:credential-store-ref> 
    <sec:default-subject> 
        <sec:realm>client-cert-realm</sec:realm> 
        <sec:id>default</sec:id>            
    </sec:default-subject> 
    <sec:role-mappings> 
        ...... 
    </sec:role-mappings> 
 </sec:security> 
 <gbean name="client-cert-realm" 
    class="org.apache.geronimo.security.realm.GenericSecurityRealm" 
    xsi:type="dep:gbeanType"> 
    <attribute name="realmName">client-cert-realm</attribute> 
        <attribute name="global">true</attribute> 
        <reference name="ServerInfo"> 
            <name>ServerInfo</name> 
        </reference> 
        <xml-reference name="LoginModuleConfiguration"> 
            <log:login-config xmlns:log="......"> 
                <log:login-module control-flag="REQUIRED" wrap-principals="false"> 
                    <log:login-domain-name>client-cert-realm</log:login-domain-name> 
                    <log:login-module-class> 
                     o.a.g.security.realm.providers.PropertiesFileNoPasswordLoginModule 
                    </log:login-module-class> 
                    <log:option name="groupsURI"> 
                        var/security/groups.properties</log:option 
                    > 
                </log:login-module> 
            </log:login-config> 
    </xml-reference> 
 </gbean> 
 <gbean name="client-cert-credential-store" 
    class="org.apache.geronimo.security.credentialstore.SimpleCredentialStoreImpl"> 
    <xml-attribute name="credentialStore"> 
        <credential-store xmlns="......"> 
            <realm name="client-cert-realm"> 
                <subject> 
                    <id>default</id> 
                    <credential> 
                        <type> 
                        o.a.g.security.credentialstore.NameCallbackHandler 
                        </type> 
                        <value>system</value> 
                   </credential> 
                </subject>                   
            </realm> 
        </credential-store> 
    </xml-attribute>      
 </gbean>            
       

?

当使用 CLIENT-CERT 认证方式时,服务端和客户端之间的证书验证在 SSL 握手阶段已经完成,即一旦握手成功,表明用户身份得到确认,故而该请求具备了受保护资源的访问权限。如 清单 12 所 示,使用了与 HTTP BASIC 认证时 Web Service 客户端类似的部署配置,使用 default-subject 配置项,并结合 Security Realm 和 Credential Store 设置,为用户会话添加默认的安全设置,使之可以访问受保护的资源。

4. 修改 Web Service 客户端部署文件中的端口值,改为 8444,即服务端新建支持 CLIENT-CERT 认证方式的 HTTPS Connector 监听端口。

5. 启动 Web Service 客户端所在 Geronimo 应用服务器之前,在命令行使用 GERONIMO_OPTS 设置以下系统属性:


表 3. CLIENT-CERT 客户端系统属性设置

属性名称 配置值 属性说明
javax.net.ssl.trustStore $YOUR_GERONIMO_HOME/gt/var/security/keystores/geronimo-default 客户端受信密钥库,包含从服务端导入的公钥信息
javax.net.ssl.trustStorePassword secret 客户端受信密钥库访问密码
javax.net.ssl.keyStore $YOUR_GERONIMO_HOME/gt/var/security/keystores/client.jks 客户端密钥库,包含客户端自身的私钥信息
javax.net.ssl.keyStorePassword secret 客户端密钥库访问密码

从表格 3 的设置可以看出,Web Service 客户端和服务端设置是完全对等的,只是客户端是通过系统属性设置,而服务端则通过 HTTPS Connector 设置。也说明了 CLIENT-CERT 本质上是双向证书认证方式。

结束语

本文以一个简单的在线书店 Web Service 应用为例,介绍了如何基于 HTTP/HTTPS 保护 SOAP 信息交互安全。概而述之,通过 HTTP BASIC/CLIENT-CERT 实现对 Web Service 应用的授权访问,而通过 SSL 确保消息传输的完整性和私密性。实际环境中,可以基于需求选择合适的安全策略。

?


原文:http://www.ibm.com/developerworks/cn/opensource/os-cn-ag-secwebs/index.html?ca=drs-

  相关解决方案