博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Cxf+wss4j的WS-Security实现【未验证】
阅读量:2352 次
发布时间:2019-05-10

本文共 14765 字,大约阅读时间需要 49 分钟。

文章来源:http://blog.csdn.net/wangchsh2008/article/details/6708270

最近一个项目预研,需要使用webservice,进行消息安全传输,客户要求包括加密和认证。我们使用的ws框架是cxf,认证是很容易做的,通过自定义实现一个Interceptor,就可以进行简单的用户和密码认证。但加密从来没有做过,在网上做了一些工作之后,发现cxf是可以通过wss4j实现签名、加密的。

根据网上的资料,做了一个demo,上传位置在:http://download.csdn.net/source/3539244 ,下载即可直接运行。
下面就过程,做一个简单说明。

WSS4J支持如下几种模式:

XML Security

    XML Signature

    XML Encryption

Tokens

    Username Tokens

    Timestamps

    SAML Tokens

这里将使用Timestamps+Encryption+Signature组合。  关于wss4j的学习,请参考apache文档。

第一步是要生成服务端及客户端密钥文件,这里用到了JDK中的keytool工具,关于Keytool的使用以及参数说明,请读者自行学习相关文档。
本文中为了方便起见,已经将命令编辑为2个bat文件。在同一目录下,执行generateServerKey.bat批处理,即可生成clientStore.jks及serverStore.jks文件(clientKey.rsa和serverKey.rsa文件用不到)。
generateKeyPair.bat

[plain] 
  1. rem @echo off  
  2. echo alias %1  
  3. echo keypass %2  
  4. echo keystoreName %3  
  5. echo KeyStorePass %4  
  6. echo keyName %5  
  7.   
  8. echo keyName %5  
  9. keytool -genkey -alias %1 -keypass %2 -keystore %3 -storepass %4  -dname "cn=%1" -keyalg RSA  
  10. keytool -selfcert -alias %1 -keystore %3 -storepass %4 -keypass %2  
  11. keytool -export -alias %1 -file %5 -keystore %3 -storepass %4  

generateServerKey.bat

[plain] 
  1. call generateKeyPair.bat apmserver apmserverpass serverStore.jks keystorePass serverKey.rsa  
  2. call generateKeyPair.bat apmclient apmclientpass clientStore.jks keystorePass clientKey.rsa  
  3. keytool -import -alias apmserver -file serverKey.rsa -keystore clientStore.jks -storepass keystorePass -noprompt  
  4. keytool -import -alias apmclient -file clientKey.rsa -keystore serverStore.jks -storepass keystorePass -noprompt  

生成的密钥文件中包含的信息:

服务端 账户:apmserver / apmserverpass

客户端 账户:apmclient / apmclientpass


如下图所示建立工程:


lib下的jar:



服务器端
,有一个对密码进行处理的类
 PasswordHandler.java
[java] 
  1. package com.db.webservice.security;  
  2.   
  3. import java.io.IOException;  
  4. import java.util.HashMap;  
  5. import java.util.Map;  
  6.   
  7. import javax.security.auth.callback.Callback;  
  8. import javax.security.auth.callback.CallbackHandler;  
  9. import javax.security.auth.callback.UnsupportedCallbackException;  
  10.   
  11. import org.apache.ws.security.WSPasswordCallback;  
  12.   
  13. /** 
  14.  * desc: comment PasswordHandler.java 
  15.  * @author Chaisson(chengshengwang) 
  16.  * @since Aug 19, 2011 5:08:30 PM 
  17.  * @vision 1.0 
  18.  */  
  19. public class PasswordHandler implements CallbackHandler {  
  20.   
  21.     private Map<String, String> passwords = new HashMap<String, String>();  
  22.   
  23.     public PasswordHandler() {  
  24.         passwords.put("apmserver""apmserverpass");  
  25.         passwords.put("apmclient""apmclientpass");  
  26.     }  
  27.   
  28.     public void handle(Callback[] callbacks) throws IOException,  
  29.             UnsupportedCallbackException {  
  30.         WSPasswordCallback pc = (WSPasswordCallback) callbacks[0];  
  31.         String id = pc.getIdentifer();  
  32.         pc.setPassword((String) passwords.get(id));  
  33.     }  
  34. }  

定义一个interface:TestService.java

[java] 
  1. package com.db.webservice;  
  2.   
  3. import javax.jws.WebParam;  
  4. import javax.jws.WebService;  
  5.   
  6. /** 
  7.  * desc: comment TestService.java 
  8.  * @author Chaisson(chengshengwang) 
  9.  * @since May 13, 2011 11:41:03 AM 
  10.  * @vision 1.0 
  11.  */  
  12. @WebService  
  13. public interface TestService {  
  14.     public String sayHello(@WebParam(name="myName") String name);  
  15.       
  16.     public String printMan(User user);  
  17. }  

实现上面的接口TestServiceImpl.java

[java] 
  1. package com.db.webservice.impl;  
  2.   
  3. import com.db.webservice.TestService;  
  4. import com.db.webservice.User;  
  5.   
  6. /** 
  7.  * desc: comment TestServiceImpl.java 
  8.  * @author Chaisson(chengshengwang) 
  9.  * @since May 13, 2011 11:41:38 AM 
  10.  * @vision 1.0 
  11.  */     
  12. public class TestServiceImpl implements TestService {  
  13.     public String sayHello(String myName){  
  14.         System.out.println("Hello World! "+myName);  
  15.         return "SUCCESS";  
  16.     }  
  17.   
  18.     public String printMan(User user) {  
  19.         StringBuffer sb = new StringBuffer();  
  20.         if(user.getAge()>=18 && user.getAge()<60){  
  21.             sb.append("He is a young man. ");  
  22.         }else if(user.getAge()>=60){  
  23.             sb.append("He is an old man. ");  
  24.         }else{  
  25.             sb.append("He is a little boy. ");  
  26.         }  
  27.           
  28.         if(user.getName()!=null){  
  29.             sb.append(" His name is "+user.getName()+". ");  
  30.         }  
  31.         if(user.getDesc()!=null){  
  32.             sb.append(" His description is that "+user.getDesc()+". ");  
  33.         }  
  34.         return sb.toString();  
  35.     }  
  36. }  

一个PO: User.java

[java] 
  1. package com.db.webservice;  
  2.   
  3. /** 
  4.  * desc: comment User.java 
  5.  * @author Chaisson(chengshengwang) 
  6.  * @since May 13, 2011 5:20:38 PM 
  7.  * @vision 1.0 
  8.  */  
  9. public class User {  
  10.       
  11.     private int age;  
  12.       
  13.     private String name;  
  14.       
  15.     private String desc;  
  16.   
  17.     //省去setter/getter  
  18. }  

还有3个配置文件:

server_insecurity_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=keystorePass

org.apache.ws.security.crypto.merlin.alias.password=apmserverpass

org.apache.ws.security.crypto.merlin.keystore.alias=apmserver

org.apache.ws.security.crypto.merlin.file=serverStore.jks


server_insecurity_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=keystorePass
#org.apache.ws.security.crypto.merlin.alias.password=apmserverpass
org.apache.ws.security.crypto.merlin.keystore.alias=apmserver
org.apache.ws.security.crypto.merlin.file=serverStore.jks

server_outsecurity_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=keystorePass
#org.apache.ws.security.crypto.merlin.alias.password=apmserverpass
#org.apache.ws.security.crypto.merlin.keystore.alias=apmserver
org.apache.ws.security.crypto.merlin.file=serverStore.jks

如果我没有看错的话,上面3个配置是一摸一样的,呵呵,仅仅是后面的有部分被注释了。

客户端,我们首先需要一个Test类,TestServiceClient.java

[java] 
  1. package com.db.webservice.test;  
  2.   
  3.   
  4.   
  5. import org.springframework.context.ApplicationContext;  
  6. import org.springframework.context.support.FileSystemXmlApplicationContext;  
  7.   
  8. import com.db.webservice.TestService;  
  9. import com.db.webservice.User;  
  10.   
  11. /** 
  12.  * desc: comment TestServiceClient.java 
  13.  * @author Chaisson(chengshengwang) 
  14.  * @since May 13, 2011 2:17:04 PM 
  15.  * @vision 1.0 
  16.  */  
  17. public class TestServiceClient {  
  18.   
  19.     /** 
  20.      * desc: 
  21.      * @Chaisson(chengshengwang) 
  22.      * @since May 13, 2011 
  23.      * @version 1.0 
  24.      * @param args 
  25.      */  
  26.     public static void main(String[] args) {  
  27.         /*JaxWsProxyFactoryBean  factory = new JaxWsProxyFactoryBean (); 
  28.         factory.setServiceClass(TestService.class); 
  29.         factory.setAddress("http://localhost:8080/TestCXF/services/MyService"); 
  30.         TestService service =(TestService)factory.create(); 
  31.         service.sayHello("Chaisson"); 
  32.          
  33.         User user = new User(); 
  34.         user.setAge(10); 
  35.         user.setName("Chaisson"); 
  36.         user.setDesc("He is a good man"); 
  37.         System.out.println(service.printMan(user));*/  
  38.           
  39.           
  40.           
  41.         ApplicationContext ctx = new FileSystemXmlApplicationContext("classpath:applicationContext.xml");     
  42.         TestService client = (TestService)ctx.getBean("client");  
  43.           
  44.         User user = new User();  
  45.         user.setAge(10);  
  46.         user.setName("Chaisson");  
  47.         user.setDesc("He is a good man");  
  48.         System.out.println(client.printMan(user));  
  49.   
  50.     }  
  51.   
  52. }  

当然也需要3个properties配置文件

insecurity_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=keystorePass

org.apache.ws.security.crypto.merlin.alias.password=apmclientpass

org.apache.ws.security.crypto.merlin.keystore.alias=apmclient

org.apache.ws.security.crypto.merlin.file=clientStore.jks


outsecurity_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=keystorePass

org.apache.ws.security.crypto.merlin.alias.password=apmclientpass

org.apache.ws.security.crypto.merlin.keystore.alias=apmclient

org.apache.ws.security.crypto.merlin.file=clientStore.jks


outsecurity_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=keystorePass
org.apache.ws.security.crypto.merlin.alias.password=apmclientpass
org.apache.ws.security.crypto.merlin.keystore.alias=apmclient
org.apache.ws.security.crypto.merlin.file=clientStore.jks
如果我没有看错的话,这回3个配置文件真的一摸一样了。
在客户端还需要加一个服务发布地址的配置文件
serverhost.properties
host.url=http://127.0.0.1:8080/TestCXF/services
最后整个工程少不了Spring配置文件:
applicationContext.xml
[html] 
  1. <beans xmlns="http://www.springframework.org/schema/beans"  
  2.     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
  3.     xmlns:jaxws="http://cxf.apache.org/jaxws"  
  4.     xsi:schemaLocation="  
  5.     http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd  
  6.     http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd">  
  7.           
  8.     <bean id="client" class="com.db.webservice.TestService"   
  9.          factory-bean="clientFactory" factory-method="create">  
  10.     </bean>        
  11.     <bean id="clientFactory" class="org.apache.cxf.jaxws.JaxWsProxyFactoryBean">  
  12.          <property name="serviceClass" value="com.db.webservice.TestService" />  
  13.          <property name="address" value="${host.url}/MyService" />  
  14.          <property name="outInterceptors">  
  15.             <list>  
  16.                 <bean class="org.apache.cxf.binding.soap.saaj.SAAJOutInterceptor" />  
  17.                 <ref bean="wss4jOutConfiguration" />  
  18.             </list>  
  19.          </property>  
  20.          <property name="inInterceptors">  
  21.             <list>  
  22.                 <bean class="org.apache.cxf.binding.soap.saaj.SAAJInInterceptor" />  
  23.                 <ref bean="wss4jInConfiguration" />  
  24.             </list>  
  25.          </property>  
  26.     </bean>   
  27.         <bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">  
  28.         <property name="locations">  
  29.             <list>  
  30.                 <value>classpath:serverhost.properties</value>  
  31.             </list>  
  32.         </property>  
  33.     </bean>  
  34.       
  35.     <bean id="wss4jOutConfiguration" class="org.apache.cxf.ws.security.wss4j.WSS4JOutInterceptor">  
  36.         <property name="properties">  
  37.             <map>  
  38.                 <entry key="action" value="Timestamp Encrypt Signature" />  
  39.                 <entry key="user" value="apmclient" />  
  40.                 <entry key="encryptionUser" value="apmserver" />  
  41.                 <entry key="signaturePropFile" value="outsecurity_sign.properties" />  
  42.                 <entry key="signatureKeyIdentifier" value="IssuerSerial" />  
  43.                 <entry key="encryptionPropFile" value="outsecurity_enc.properties" />  
  44.                 <entry>  
  45.                     <key>  
  46.                         <value>passwordCallbackRef</value>  
  47.                     </key>  
  48.                     <ref bean="passwordCallback" />  
  49.                 </entry>  
  50.             </map>  
  51.         </property>  
  52.     </bean>  
  53.       
  54.     <bean id="wss4jInConfiguration" class="org.apache.cxf.ws.security.wss4j.WSS4JInInterceptor">  
  55.         <property name="properties">  
  56.             <map>  
  57.                 <entry key="action" value="Timestamp Encrypt Signature" />  
  58.                 <entry key="user" value="apmclient" />  
  59.                 <entry key="decryptionPropFile" value="insecurity_enc.properties" />  
  60.                 <entry key="enableSignatureConfirmation" value="true" />  
  61.                 <entry key="signaturePropFile" value="outsecurity_sign.properties" />  
  62.                 <entry key="signatureKeyIdentifier" value="IssuerSerial" />  
  63.                 <entry>  
  64.                     <key>  
  65.                         <value>passwordCallbackRef</value>  
  66.                     </key>  
  67.                     <ref bean="passwordCallback" />  
  68.                 </entry>  
  69.             </map>  
  70.         </property>  
  71.     </bean>     
  72.     <bean id="passwordCallback" class="com.db.webservice.security.PasswordHandler"/>    
  73. </beans>    

cxf的配置文件:

cxf-servlet.xml

[html] 
  1. <?xml version="1.0" encoding="UTF-8"?>     
  2. <beans xmlns="http://www.springframework.org/schema/beans"    
  3.     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"    
  4.     xmlns:jaxws="http://cxf.apache.org/jaxws"    
  5.     xsi:schemaLocation="     
  6. http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd     
  7. http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd">     
  8.     <import resource="classpath:META-INF/cxf/cxf.xml" />      
  9.     <import resource="classpath:META-INF/cxf/cxf-extension-soap.xml" />      
  10.     <import resource="classpath:META-INF/cxf/cxf-servlet.xml" />   
  11.       
  12.     <bean id="testService" class="com.db.webservice.impl.TestServiceImpl" />   
  13.     <jaxws:endpoint id="myService" implementor="#testService" address="/MyService" >  
  14.         <jaxws:inInterceptors>  
  15.             <bean class="org.apache.cxf.interceptor.LoggingInInterceptor"/>   
  16.             <bean class="org.apache.cxf.binding.soap.saaj.SAAJInInterceptor"/>  
  17.             <ref bean="wss4jInConfiguration"/>  
  18.         </jaxws:inInterceptors>  
  19.         <jaxws:outInterceptors>  
  20.             <bean class="org.apache.cxf.interceptor.LoggingOutInterceptor"/>  
  21.             <bean class="org.apache.cxf.binding.soap.saaj.SAAJOutInterceptor"/>  
  22.             <ref bean="wss4jOutConfiguration"/>  
  23.         </jaxws:outInterceptors>  
  24.     </jaxws:endpoint>   
  25.       
  26.     <!--   
  27.     <bean id="client" class="com.db.webservice.TestService"   
  28.          factory-bean="clientFactory" factory-method="create"/>   
  29.     <bean id="clientFactory" class="org.apache.cxf.jaxws.JaxWsProxyFactoryBean">  
  30.          <property name="serviceClass" value="com.db.webservice.TestService"/>  
  31.          <property name="address" value="http://localhost:8080/TestCXF/services/MyService"/>  
  32.     </bean>    -->     
  33.       
  34.       
  35.     <bean id="wss4jInConfiguration" class="org.apache.cxf.ws.security.wss4j.WSS4JInInterceptor">  
  36.         <property name="properties">  
  37.             <map>  
  38.                 <entry key="action" value="Timestamp Encrypt Signature"/>  
  39.                 <entry key="decryptionPropFile" value="server_insecurity_enc.properties"/>  
  40.                 <entry key="signaturePropFile" value="server_insecurity_sign.properties"/>  
  41.                 <entry>  
  42.                     <key>  
  43.                         <value>passwordCallbackRef</value>  
  44.                     </key>  
  45.                     <ref bean="passwordCallback"/>  
  46.                 </entry>  
  47.             </map>  
  48.         </property>  
  49.     </bean>  
  50.       
  51.     <bean id="wss4jOutConfiguration" class="org.apache.cxf.ws.security.wss4j.WSS4JOutInterceptor">  
  52.         <property name="properties">  
  53.             <map>  
  54.                 <entry key="action" value="Timestamp Encrypt Signature"/>  
  55.                 <entry key="user" value="apmserver" />  
  56.                 <entry key="encryptionUser" value="apmclient" />  
  57.                 <entry key="encryptionPropFile" value="server_outsecurity_enc.properties"/>  
  58.                 <entry key="signaturePropFile" value="server_insecurity_sign.properties"/>  
  59.                 <entry>  
  60.                     <key>  
  61.                         <value>passwordCallbackRef</value>  
  62.                     </key>  
  63.                     <ref bean="passwordCallback"/>  
  64.                 </entry>  
  65.             </map>  
  66.         </property>  
  67.     </bean>  
  68.        
  69.     <bean id="passwordCallback" class="com.db.webservice.security.PasswordHandler"/>   
  70. </beans>  

还有一个web.xml,也简单提一下吧

[html] 
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <web-app version="2.4"   
  3.     xmlns="http://java.sun.com/xml/ns/j2ee"   
  4.     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"   
  5.     xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee   
  6.     http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">  
  7.       
  8.   <servlet>  
  9.     <description>cxfServlet</description>  
  10.     <display-name>cxfServlet</display-name>  
  11.     <servlet-name>cxfServlet</servlet-name>  
  12.     <servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class>  
  13.     <load-on-startup>2</load-on-startup>  
  14.   </servlet>  
  15.   
  16.   <servlet-mapping>  
  17.     <servlet-name>cxfServlet</servlet-name>  
  18.     <url-pattern>/services/*</url-pattern>  
  19.   </servlet-mapping>  
  20.     
  21.   <context-param>    
  22.     <param-name>contextConfigLocation</param-name>    
  23.     <param-value>WEB-INF/cxf-servlet.xml</param-value>    
  24.   </context-param>    
  25.   <listener>    
  26.     <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>    
  27.   </listener>    
  28.     
  29.       
  30.   <welcome-file-list>  
  31.     <welcome-file>index.jsp</welcome-file>  
  32.   </welcome-file-list>  
  33. </web-app>  

好了,project搭建完毕,在最后进行测试的时候,发生了很多问题。

如果你从http://download.csdn.net/source/3539244位置下载了我的demo,直接run的话,也是会报异常的。因为某些国家对加密算法有一定限制,所以SUN公司在发布JDK的时候里面的策略文件是限制版的。需要到SUN公司网站上下载非限制版的策略文件进行替换。

解决的办法,请参考我的另一篇文章http://blog.csdn.net/wangchsh2008/article/details/6708718


本文参考了以下一些文章:

http://blog.csdn.net/kunshan_shenbin/article/details/3813000

http://blog.myspace.cn/e/403951535.htm 
http://cxf.apache.org/docs/ws-security.html

你可能感兴趣的文章
Ibatis代码自动生成工具
查看>>
ant build.xml教程详解
查看>>
彻底理解ThreadLocal
查看>>
localhost与127.0.0.1的区别
查看>>
windows下的host文件在哪里,有什么作用?
查看>>
【工具】人脸识别比对开放平台汇总
查看>>
基于DirectUI技术开发的发卡系统
查看>>
STM32 HAL库、标准外设库、LL库(STM32 Embedded Software)
查看>>
51和AVR单片机
查看>>
DSP开发板
查看>>
stm32标准外设库和芯片资料下载地址
查看>>
ARM Keil MDK开发STM32工程模板
查看>>
NoSQL分类及常用软件
查看>>
ubuntu 16.04安装nVidia显卡驱动和cuda/cudnn踩坑过程
查看>>
基于STM32CubeMX创建STM32L496ZGTx的工程
查看>>
如何通过OpenFace实现人脸识别框架
查看>>
Angle和XBGoost以及Spark的性能对比
查看>>
IOS CoreImage实现人脸识别
查看>>
Tensorflow的高级封装
查看>>
Storm 1.1.0 集群安装
查看>>