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

接上篇记录一下使用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配置

 



  cxfjaxwssecurityserver1
  
	
	      contextConfigLocation
	      WEB-INF/beans.xml
	
  
    
        
                        org.springframework.web.context.ContextLoaderListener
        
    
      
        Apache CXF Endpoint
        cxf
        cxf
        org.apache.cxf.transport.servlet.CXFServlet
        1
    
    
        cxf
        /services/*
    
    
        60
     





 2,spring配置

 


	
   	
	
   	  
         
   
	
	
		
	
	
	
		
			
				
				
					
								
								
								
						
				
	
    
     		
		
					
		
		
				
			
			
					
  	 	    
    
 

 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 outProps = new HashMap();
		
		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 passwds = new HashMap();
	
	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: CN=merrick.site524604543iW2uP138lAETFgb8X7mEZabg0hrdHP9wBoGiNza7RZLkrYTd8zFiHN3rcUek+6DnWIJMINHkH6W5jjs/ijbPjr5/3bHGATU5MjIPkZXlTOdS0SRPO9pKEJg/yJ75jxiWRTJI+ji59PbCUR4bzPKB1by/pzLkVdaJBdqr07usAybk7/8WXy0LgN2NSMAFaDyZIv/d3C2Qxd1fYp+noDhQ0u0+6yYi3tbH4VKUKyRea19/B+LwwZSpXsooGXXjf7NY+NCl9+c5lXpbJd+c5Tl+vGHqspAhINhO4Pylhxen2CT8Vnt192bUBflTe2wHL/jampSMZ2cQR6REbjsw0vUMRA==oQetPKFHYFuzDqTIW2pwtNb7YOs=BrnWlHeUzwDkps7JO+DYwup2JiD6tOjI/B1xDjTri2kFa0wk/Y7xHIGtxiu+9YWT4iC0UeFtIYXuABi7+j75Qv+fUJ/PsYBrwBz4SHEuDy9ydMY12UwMJWys7zXzIoRAjSmHMX+qnejzrtRuy5Z+joZmNV0tmT2Lm9tft8pNAewhefea7Xj2ylYGSZ5XjZrx0vAru3AZiAwtMSkd/zgDKV52B4jF6Wo3Y5a57AEjvkqjc87x0WQzeqfjM9CStYSVAFgOAQXiMGe6uk6zHd7J/Viu3aoIfbEVe4wBfXeAGjr7kX6w25OvQMWb7WiY/hxggTwVxtTutLtUx42PpdXtow==CN=merrick.site374919786yFthTTriWkD4gbX4UyvCs6hixP2y5i1fBwAF/jmYbyTuYpObB9H98ACFxnLQEbje6v4Dg6H15R2OwNdHGwe57aWGHl8maT4bUUMWofd1Df6Mu7zhyUjKjpcJUv6qBNB4Bt94u4obsTXvmp7ayfJR3RNRxcrmkC/76bVUMM3Z6ze6716H3YfOd026HuA1Ru5b
--------------------------------------
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: <<A Tale of two citiest>>,2001,English
--------------------------------------

 

你可能感兴趣的:(安全机制)