SOAP WebService以CXF实现WS-Security之xml签名及加密

标签: soap webservice cxf | 发表时间:2016-11-08 12:59 | 作者:fall10
出处:http://www.iteye.com

接上篇,记录一下使用apache cxf和spring使用自签名数字证书实现WebService服务端及客户端的xml签名、加密以及解密和签名验证;

这里仅针对客户端加密和签名并在服务端实现解密及签名验证的单向认证的情形,双向认证可以参照官方sample改进;

实现:

客户端使用客户端私钥进行消息签名、客户端使用服务端公钥消息加密;

服务端使用客户端公钥进行签名验证、服务端使用服务端私钥进行消息解密;

对于xml签名流程理论参考: http://www.ibm.com/developerworks/cn/xml/x-cn-java6xmlsignature/

 

基本流程:

一、密钥库生成(比较关键)

1,生成客户端用于xml签名的证书密钥库,生成服务端用于解密的私钥库

2,导出客户端证书、导出服务端证书;

3,客户端证书导入并生成供服务端使用的信任证书库,供服务端验证签名;

4,服务端证书导入并生成供客户端使用的信任证书库,供客户端加密SOAP消息;

keytool -genkey -alias merrickclientprivate -keypass passwd -keystore client_keystore.jks -storepass passwd -dname "CN=merrick.site" -keyalg RSA

keytool -selfcert -keystore client_keystore.jks -alias merrickclientprivate -storepass passwd -keypass passwd

keytool -export -alias merrickclientprivate -file client_pubcert.cer -keystore client_keystore.jks -storepass passwd


keytool -genkey -alias merrickserverprivate -keypass passwd -keystore server_keystore.jks -storepass passwd -dname "CN=merrick.site" -keyalg RSA

keytool -selfcert -keystore server_keystore.jks -alias merrickserverprivate -storepass passwd -keypass passwd

keytool -export -alias merrickserverprivate -file server_pubcert.cer -keystore server_keystore.jks -storepass passwd


keytool -import -alias merrickclientpublic -file client_pubcert.cer -keystore server_trust.jks -storepass passwd

keytool -import -alias merrickserverpublic -file server_pubcert.cer -keystore client_trust.jks -storepass passwd

 

二、WebProject服务端

[WebService开放接口及ServiceBean见前篇有关usernametoken认证:http://fall10.iteye.com/blog/2334924]

1,web.xml配置

 

<?xml version="1.0" encoding="UTF-8"?>
<web-app 
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
	xmlns="http://java.sun.com/xml/ns/javaee" 
	xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" 
	id="WebApp_ID" 
	version="3.0">
  <display-name>cxfjaxwssecurityserver1</display-name>
  
	<context-param>
	      <param-name>contextConfigLocation</param-name>
	      <param-value>WEB-INF/beans.xml</param-value>
	</context-param>
  
    <listener>
        <listener-class>
                        org.springframework.web.context.ContextLoaderListener
        </listener-class>
    </listener>
      <servlet>
        <description>Apache CXF Endpoint</description>
        <display-name>cxf</display-name>
        <servlet-name>cxf</servlet-name>
        <servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>cxf</servlet-name>
        <url-pattern>/services/*</url-pattern>
    </servlet-mapping>
    <session-config>
        <session-timeout>60</session-timeout>
    </session-config> 

</web-app>



 2,spring配置

 

<?xml version="1.0" encoding="UTF-8"?>
<beans 
	xmlns="http://www.springframework.org/schema/beans" 
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
	xmlns:jaxws="http://cxf.apache.org/jaxws" 
	xmlns:soap="http://cxf.apache.org/bindings/soap" 
	xmlns:util="http://www.springframework.org/schema/util"
	xsi:schemaLocation=" 
	http://www.springframework.org/schema/beans 
	http://www.springframework.org/schema/beans/spring-beans.xsd 
	http://cxf.apache.org/bindings/soap 
	http://cxf.apache.org/schemas/configuration/soap.xsd 
	http://cxf.apache.org/jaxws 
	http://cxf.apache.org/schemas/jaxws.xsd 
	http://www.springframework.org/schema/util 
    http://www.springframework.org/schema/util/spring-util.xsd">	
   	
	<import resource="classpath:META-INF/cxf/cxf.xml"/>
   	<import resource="classpath*:META-INF/cxf/cxf-extension-*.xml" />  
    <import resource="classpath:META-INF/cxf/cxf-servlet.xml"/>     
   
	<bean id="logIn" class="org.apache.cxf.interceptor.LoggingInInterceptor" />
	<bean id="logOut" class="org.apache.cxf.interceptor.LoggingOutInterceptor" />
	<bean id="saajIn" class="org.apache.cxf.binding.soap.saaj.SAAJInInterceptor" />	
	<bean id="mypasswdcallback" class="cxf.jaxws.basic.server.PasswdCallback"/>
	
	<bean id="wss4jin" class="org.apache.cxf.ws.security.wss4j.WSS4JInInterceptor">
		<constructor-arg>
			<map>
				<entry key="action" value="Signature Encrypt"/>
				<entry key="passwordCallbackRef" >
					<ref  bean="mypasswdcallback"/>
				</entry>				
				<entry key="decryptionPropFile" value="../prop/server_decryption.properties" /><!-- 基于java类路径 -->				
				<entry key="signaturePropFile" value="../prop/server_versign.properties"/>				
			</map>			
		</constructor-arg>		
	</bean>
    
    <jaxws:endpoint id="bookinfoservice" address="/bookinfo" implementor="cxf.jaxws.basic.server.BookServiceImpl" > 		
		<jaxws:outInterceptors>
			<ref bean="logOut"/>		
		</jaxws:outInterceptors>
		
		<jaxws:inInterceptors>		
			<ref bean="logIn"/>
			<ref bean="saajIn"/>
			<ref bean="wss4jin"/>		
  	 	</jaxws:inInterceptors>    
    </jaxws:endpoint>
 
</beans>

 3,密码验证回调函数(虽说property文件中已配置,但是还是需要设置一下各密钥用户的密码)

 

public class PasswdCallback implements CallbackHandler {
	@Override
	public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {
		
		for (int i = 0; i < callbacks.length; i++) {
			WSPasswordCallback pc = (WSPasswordCallback)callbacks[i];
			pc.setPassword("passwd");/**使用数字证书加密、签名,同样也必须在这里设置密钥库的密码*/			
			System.out.println("Server " + pc.getIdentifier());
			System.out.println("Server " + pc.getPassword());
		}
	}
}

 

 

3,服务端使用密钥库相关信息属性配置文件

       
        server_versign.properties//验证签名用公钥信息

 

org.apache.ws.security.crypto.provider=org.apache.ws.security.components.crypto.Merlin
org.apache.ws.security.crypto.merlin.keystore.type=jks
org.apache.ws.security.crypto.merlin.keystore.password=passwd
org.apache.ws.security.crypto.merlin.keystore.alias=merrickclientpublic
org.apache.ws.security.crypto.merlin.keystore.file=../keys/server_trust.jks

     server_decryption.properties//解密用私钥信息

 

org.apache.ws.security.crypto.provider=org.apache.ws.security.components.crypto.Merlin
org.apache.ws.security.crypto.merlin.keystore.type=jks
org.apache.ws.security.crypto.merlin.keystore.password=passwd
org.apache.ws.security.crypto.merlin.keystore.alias=merrickserverprivate
org.apache.ws.security.crypto.merlin.keystore.file=../keys/server_keystore.jks

 三、Java Webservice客户端

 [客户端WebServiceClient及ServiceBean见前篇]

1,纯java客户端调用代码

 

public static void clientwith_UserTokenAuth_withoutSpring() throws Throwable {
		Map<String, Object> outProps = new HashMap<String, Object>();
		
		outProps.put(WSHandlerConstants.ACTION, 
				WSHandlerConstants.SIGNATURE	+ " " + 
				WSHandlerConstants.ENCRYPT			    
				);

		outProps.put(WSHandlerConstants.PW_CALLBACK_CLASS, "autoclient.test.ClientPasswdCallback");		
		outProps.put(WSHandlerConstants.SIG_PROP_FILE,"autoclient/test/clientside_sign.properties");		
		outProps.put(WSHandlerConstants.SIGNATURE_USER, "merrickclientprivate");			
		outProps.put(WSHandlerConstants.ENCRYPTION_USER, "merrickserverpublic");
		outProps.put(WSHandlerConstants.ENC_PROP_FILE, "autoclient/test/clientside_enc.properties");
		
		JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean();
		factory.setServiceClass(cxfclient.jaxws.auto.BookService.class);
		factory.setAddress("http://localhost:8080/cxfjaxwssecurityserver1/services/bookinfo");
		factory.getOutInterceptors().add(new WSS4JOutInterceptor(outProps));
		
		cxfclient.jaxws.auto.BookService service = (cxfclient.jaxws.auto.BookService) factory.create();
		DtoBean b = new DtoBean();
		b.setId(1);
		b.setName("a");	 
		String response = service.getOneBookInfo(b);		
		System.out.println(response);
}
 

 

 设定密码的回调方法

public class ClientPasswdCallback implements CallbackHandler {
	
	private Map<String,String> passwds = new HashMap<String,String>();
	
	public ClientPasswdCallback() {
		
	}

	@Override
	public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {
		
		for (int i = 0; i < callbacks.length; i++) {
			WSPasswordCallback pc = (WSPasswordCallback)callbacks[i];
			pc.setPassword("passwd");	/**使用数字证书加密、签名,同样也必须在这里设置密钥库的密码*/
			
			System.out.println("Client " + pc.getIdentifier());
			System.out.println("Client " + pc.getPassword());
		}
	}
}
 2,客户端密钥配置属性文件

 

 clientside_enc.properties//加密用

 

org.apache.ws.security.crypto.provider=org.apache.ws.security.components.crypto.Merlin
org.apache.ws.security.crypto.merlin.keystore.type=jks
org.apache.ws.security.crypto.merlin.keystore.password=passwd
org.apache.ws.security.crypto.merlin.keystore.alias=merrickserverpublic
org.apache.ws.security.crypto.merlin.keystore.file=autoclient/test/client_trust.jks
 

 

clientside_sign.properties//签名用

org.apache.ws.security.crypto.provider=org.apache.ws.security.components.crypto.Merlin
org.apache.ws.security.crypto.merlin.keystore.type=jks
org.apache.ws.security.crypto.merlin.keystore.password=passwd
org.apache.ws.security.crypto.merlin.keystore.alias=merrickclientprivate
org.apache.ws.security.crypto.merlin.keystore.file=autoclient/test/client_keystore.jks

 

四、客户端发起Webservice请求测试

在服务端可见log

信息: Inbound Message
----------------------------
ID: 1
Address: http://localhost:8080/cxfjaxwssecurityserver1/services/bookinfo
Encoding: UTF-8
Http-Method: POST
Content-Type: text/xml; charset=UTF-8
Headers: {Accept=[*/*], cache-control=[no-cache], connection=[keep-alive], content-type=[text/xml; charset=UTF-8], host=[localhost:8080], pragma=[no-cache], SOAPAction=[""], transfer-encoding=[chunked], user-agent=[Apache CXF 3.1.6]}
Payload: <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"><SOAP-ENV:Header xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"><wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" soap:mustUnderstand="1"><xenc:EncryptedKey xmlns:xenc="http://www.w3.org/2001/04/xmlenc#" Id="EK-7424b921-ca58-4c0c-925c-69efcf11de8e"><xenc:EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#rsa-oaep-mgf1p"/><ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#"><wsse:SecurityTokenReference><ds:X509Data><ds:X509IssuerSerial><ds:X509IssuerName>CN=merrick.site</ds:X509IssuerName><ds:X509SerialNumber>524604543</ds:X509SerialNumber></ds:X509IssuerSerial></ds:X509Data></wsse:SecurityTokenReference></ds:KeyInfo><xenc:CipherData><xenc:CipherValue>iW2uP138lAETFgb8X7mEZabg0hrdHP9wBoGiNza7RZLkrYTd8zFiHN3rcUek+6DnWIJMINHkH6W5jjs/ijbPjr5/3bHGATU5MjIPkZXlTOdS0SRPO9pKEJg/yJ75jxiWRTJI+ji59PbCUR4bzPKB1by/pzLkVdaJBdqr07usAybk7/8WXy0LgN2NSMAFaDyZIv/d3C2Qxd1fYp+noDhQ0u0+6yYi3tbH4VKUKyRea19/B+LwwZSpXsooGXXjf7NY+NCl9+c5lXpbJd+c5Tl+vGHqspAhINhO4Pylhxen2CT8Vnt192bUBflTe2wHL/jampSMZ2cQR6REbjsw0vUMRA==</xenc:CipherValue></xenc:CipherData><xenc:ReferenceList><xenc:DataReference URI="#ED-5e63bd7f-3156-4e11-92aa-f88b81391d2e"/></xenc:ReferenceList></xenc:EncryptedKey><ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#" Id="SIG-c05f922e-e2e6-403a-9006-603f5ebc68a8"><ds:SignedInfo><ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"><ec:InclusiveNamespaces xmlns:ec="http://www.w3.org/2001/10/xml-exc-c14n#" PrefixList="soap"/></ds:CanonicalizationMethod><ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/><ds:Reference URI="#id-48c8406f-5918-42ba-9315-af0078a34f82"><ds:Transforms><ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/></ds:Transforms><ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/><ds:DigestValue>oQetPKFHYFuzDqTIW2pwtNb7YOs=</ds:DigestValue></ds:Reference></ds:SignedInfo><ds:SignatureValue>BrnWlHeUzwDkps7JO+DYwup2JiD6tOjI/B1xDjTri2kFa0wk/Y7xHIGtxiu+9YWT4iC0UeFtIYXuABi7+j75Qv+fUJ/PsYBrwBz4SHEuDy9ydMY12UwMJWys7zXzIoRAjSmHMX+qnejzrtRuy5Z+joZmNV0tmT2Lm9tft8pNAewhefea7Xj2ylYGSZ5XjZrx0vAru3AZiAwtMSkd/zgDKV52B4jF6Wo3Y5a57AEjvkqjc87x0WQzeqfjM9CStYSVAFgOAQXiMGe6uk6zHd7J/Viu3aoIfbEVe4wBfXeAGjr7kX6w25OvQMWb7WiY/hxggTwVxtTutLtUx42PpdXtow==</ds:SignatureValue><ds:KeyInfo Id="KI-06fd1e1c-73b6-4851-b8c1-56836c6dd89f"><wsse:SecurityTokenReference xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" wsu:Id="STR-40b02bc9-43e7-40cf-9d3d-408c5d00d06b"><ds:X509Data><ds:X509IssuerSerial><ds:X509IssuerName>CN=merrick.site</ds:X509IssuerName><ds:X509SerialNumber>374919786</ds:X509SerialNumber></ds:X509IssuerSerial></ds:X509Data></wsse:SecurityTokenReference></ds:KeyInfo></ds:Signature></wsse:Security></SOAP-ENV:Header><soap:Body xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" wsu:Id="id-48c8406f-5918-42ba-9315-af0078a34f82"><xenc:EncryptedData xmlns:xenc="http://www.w3.org/2001/04/xmlenc#" Id="ED-5e63bd7f-3156-4e11-92aa-f88b81391d2e" Type="http://www.w3.org/2001/04/xmlenc#Content"><xenc:EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#aes128-cbc"/><ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#"><wsse:SecurityTokenReference xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:wsse11="http://docs.oasis-open.org/wss/oasis-wss-wssecurity-secext-1.1.xsd" wsse11:TokenType="http://docs.oasis-open.org/wss/oasis-wss-soap-message-security-1.1#EncryptedKey"><wsse:Reference URI="#EK-7424b921-ca58-4c0c-925c-69efcf11de8e"/></wsse:SecurityTokenReference></ds:KeyInfo><xenc:CipherData><xenc:CipherValue>yFthTTriWkD4gbX4UyvCs6hixP2y5i1fBwAF/jmYbyTuYpObB9H98ACFxnLQEbje6v4Dg6H15R2OwNdHGwe57aWGHl8maT4bUUMWofd1Df6Mu7zhyUjKjpcJUv6qBNB4Bt94u4obsTXvmp7ayfJR3RNRxcrmkC/76bVUMM3Z6ze6716H3YfOd026HuA1Ru5b</xenc:CipherValue></xenc:CipherData></xenc:EncryptedData></soap:Body></soap:Envelope>
--------------------------------------
Server merrickserverprivate
Server passwd
---Invoking getOneBookInfo, DTOBean: 1,a
十一月 08, 2016 10:12:39 上午 org.apache.cxf.services.BookServiceImplService.BookServiceImplPort.BookService
信息: Outbound Message
---------------------------
ID: 1
Response-Code: 200
Encoding: UTF-8
Content-Type: text/xml
Headers: {}
Payload: <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"><soap:Body><ns2:getOneBookInfoResponse xmlns:ns2="http://server.basic.jaxws.cxf/"><return>&lt;&lt;A Tale of two citiest&gt;&gt;,2001,English</return></ns2:getOneBookInfoResponse></soap:Body></soap:Envelope>
--------------------------------------

 



已有 0 人发表留言,猛击->> 这里<<-参与讨论


ITeye推荐



相关 [soap webservice cxf] 推荐:

SOAP WebService以CXF实现WS-Security之xml签名及加密

- - 编程语言 - ITeye博客
接上篇,记录一下使用apache cxf和spring使用自签名数字证书实现WebService服务端及客户端的xml签名、加密以及解密和签名验证;. 这里仅针对客户端加密和签名并在服务端实现解密及签名验证的单向认证的情形,双向认证可以参照官方sample改进;. 客户端使用客户端私钥进行消息签名、客户端使用服务端公钥消息加密;.

SOAP Webservice和RESTful Webservice

- - 人月神话的BLOG
REST是一种架构风格,其核心是面向资源,REST专门针对网络应用设计和开发方式,以降低开发的复杂性,提高系统的可伸缩性. REST提出设计概念和准则为:. 1.网络上的所有事物都可以被抽象为资源(resource). 2.每一个资源都有唯一的资源标识(resource identifier),对资源的操作不会改变这些标识.

WebService之JAX-WS、CXF、Spring3.0+

- - 博客园_首页
          面对工作的需要,web服务这一块一直都在身边转悠着. 既然工作中需要这些,作为程序员就应该去了解和学习. 下面主要简述采用CXF+Spring+JAX-WS来发布WebService服务,以及创建客户端调用服务.          1、先了解关于WebService的相关概念以及一些专有名词的解释:.

webservice编程基础—cxf

- - ITeye博客
最近研究了一下cxf的使用,主要的步骤如下:. 下载最新的cxf包apache-cxf-2.6.2.tar.zip,并解压,有一个lib文件,里面的jar包,就是webservice需要的(不完全需要,看你的应用,但是懒的分),加载进你的webservice的工程即可. 配置两个配置文件,为beans.xml和web.xml,内容如下:.

CXF WEBSERVICE 安全验证

- - 企业架构 - ITeye博客
CXF 封装的接口,不希望对外暴露 WSDL结构,找到的CXF安全认证技术都是基于拦截器,在调用的时候返回认证错误信息, 不能保护WSDL不被看到,后来看到别人的一个实现方式最简单有效,基于URL拦截的安全保护,用FILTER. 现在把这2种安全保护都记录下来,备用. 参考: http://www.myexception.cn/open-source/1505475.html.

webService学习之cxf与spring的简单整合

- - 企业架构 - ITeye博客
一:先把cxf的jar包导进去,我是直接在官网下载的cxf的包,解压后直接把lib文件夹里的jar一次.    性全部丢进去了,因为在学习,还不知道哪些包要哪些包不要的,所以干脆直接放进去. . . .

SOAP的S是Simple

- Jo - 酷壳 - CoolShell.cn
曾经有一个争论,一边是站在SOAP这边的人,另一边则是其它人. 站在SOAP这边人,当他们在争论SOAP和Web Service框架的复杂度时,SOAP这边的人说,在引入那些WS-*东东之前,SOAP的确是简单的,这就是为什么SOAP的第一个字母S就是Simple. 在2000年的时候,有一个苦恼的程序员,.

webservice认证

- - 行业应用 - ITeye博客
1、服务器端,增加拦截认证--ServerPasswordCallback.java.                 throw new WSSecurityException("用户不匹配.                 throw new WSSecurityException("密码不匹配.

REST 与 SOAP巅峰对话

- - CSDN博客互联网推荐文章
随着Restful的流行,soap似乎有点贵族落寞了. 下面我们先详细分析一下他们的各自的特点. REST(Representational State Transfer)是 Roy Fielding 提出的一个描述互联系统架构风格的名词. Web 本质上由各种各样的资源组成,资源由 URI 唯一标识.

WebService性能测试

- - ImportNew
(本文也会在最下面通俗的介绍). 这里给一个站内大哥的讲解: http://www.cnblogs.com/Leo_wl/archive/2010/05/20/1740205.html. 简单点就是测试WebService的一个工具. 官网地址: http://www.soapui.org/. ps:官网是英语的,如果你英语不好的话可以使用谷歌浏览器或360极速浏览器,它可以自动把英文转换成中文.