鑒于很多系統需要實施WS-Security的標準,我們在SpringSide中提供了XFire+WSS4J的Demo,本文介紹SpringSide中Spring+XFire+WSS4J的基本配置
[WebService Server端配置]第一,創建一個基本的BookService

public?interface?BookService?
{

????/**?*//**
?????*?按書名模糊查詢圖書
?????*/
????List?findBooksByName(String?name);


????/**?*//**
?????*?查找目錄下的所有圖書
?????*
?????*?@param?categoryId?如果category為null或“all”,?列出所有圖書。
?????*/
????List?findBooksByCategory(String?categoryId);


????/**?*//**
?????*?列出所有分類.
?????*
?????*?@return?List<Category>,或是null。
?????*/
????List?getAllCategorys();
}第二,接口擴展,即Extend基本的BookService,在XFire中,不同的WSS4J策略需要針對不同的ServiceClass,否則<inHandlers>里面的定義會Overlap。

public?interface?BookServiceWSS4JEnc??extends?BookService?
{

}
public?interface?BookServiceWSS4JSign??extends?BookService?
{

}第三,配置Spring的ApplicationContext文件
????<!--BookService?基類-->
????<bean?id="baseWebService"?class="org.codehaus.xfire.spring.remoting.XFireExporter"?abstract="true">
????????<property?name="serviceFactory"?ref="xfire.serviceFactory"/>
????????<property?name="xfire"?ref="xfire"/>
????</bean>

????<bean?class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
????????<property?name="mappings">
????????????<value>
????????????????/BookService=bookService
????????????????/BookServiceWSS4J=bookServiceWSS4J
????????????????/BookServiceWSS4JEnc=bookServiceWSS4JEnc
????????????????/BookServiceWSS4JSign=bookServiceWSS4JSign
????????????</value>
????????</property>
????</bean>

???<!--(1)BookWebService?不需要認證-->
????<bean?id="bookService"?class="org.codehaus.xfire.spring.remoting.XFireExporter">
????????<property?name="serviceFactory"?ref="xfire.serviceFactory"/>
????????<property?name="xfire"?ref="xfire"/>
????????<property?name="serviceBean"?ref="bookManager"/>
????????<property?name="serviceClass"?value="org.springside.bookstore.plugins.xfire.service.BookService"/>
????</bean>

????<!--??(3)BookWebService?使用?WSS4J驗證-->
????<bean?id="bookServiceWSS4J"?class="org.codehaus.xfire.spring.remoting.XFireExporter">
????????<property?name="serviceBean"?ref="bookManager"/>
????????<property?name="serviceClass"?value="org.springside.bookstore.plugins.xfire.service.BookServiceWSS4J"/>
????????<property?name="inHandlers">
????????????<list>
????????????????<ref?bean="domInHandler"/>
????????????????<ref?bean="wss4jInHandler"/>
????????????????<ref?bean="validateUserTokenHandler"/>
????????????</list>
????????</property>
????</bean>

????<bean?id="domInHandler"?class="org.codehaus.xfire.util.dom.DOMInHandler"/>

????<bean?id="wss4jInHandler"?class="org.codehaus.xfire.security.wss4j.WSS4JInHandler">
????????<property?name="properties">
????????????<props>
????????????????<prop?key="action">UsernameToken</prop>
????????????????<prop?key="passwordCallbackClass">org.springside.bookstore.plugins.xfire.wss4j.PasswordHandler</prop>
????????????</props>
????????</property>
????</bean>

????<bean?id="validateUserTokenHandler"?class="org.springside.bookstore.plugins.xfire.wss4j.WSS4JTokenHandler"/>
????
????<!--??(4)BookWebService?使用?WSS4J驗證?Encrypt模式-->
????<bean?id="bookServiceWSS4JEnc"?class="org.codehaus.xfire.spring.remoting.XFireExporter">
????????<property?name="serviceBean"?ref="bookManager"/>
????????<property?name="serviceClass"?value="org.springside.bookstore.plugins.xfire.service.BookServiceWSS4JEnc"/>
????????<property?name="inHandlers">
????????????<list>
????????????????<ref?bean="domInHandler"/>
????????????????<ref?bean="wss4jInHandlerEnc"/>
????????????????<ref?bean="validateUserTokenHandler"/>
????????????</list>
????????</property>
????</bean>
????????
????<bean?id="wss4jInHandlerEnc"?class="org.codehaus.xfire.security.wss4j.WSS4JInHandler">
????????<property?name="properties">
??????????<props>
????????????<prop?key="action">Encrypt</prop>
????????????<prop?key="decryptionPropFile">org/springside/bookstore/plugins/xfire/wss4j/insecurity_enc.properties</prop>
????????????<prop?key="passwordCallbackClass">org.springside.bookstore.plugins.xfire.wss4j.PasswordHandler</prop>
??????????</props>
????????</property>
????</bean>
????
????<!--??(5)BookWebService?使用?WSS4J驗證?Signature模式-->
????<bean?id="bookServiceWSS4JSign"?class="org.codehaus.xfire.spring.remoting.XFireExporter">
????????<property?name="serviceBean"?ref="bookManager"/>
????????<property?name="serviceClass"?value="org.springside.bookstore.plugins.xfire.service.BookServiceWSS4JSign"/>
????????<property?name="inHandlers">
????????????<list>
????????????????<ref?bean="domInHandler"/>
????????????????<ref?bean="wss4jInHandlerSign"/>
????????????????<ref?bean="validateUserTokenHandler"/>
????????????</list>
????????</property>
????</bean>
????
????<bean?id="wss4jInHandlerSign"?class="org.codehaus.xfire.security.wss4j.WSS4JInHandler">
????????<property?name="properties">
??????????<props>
????????????<prop?key="action">Signature</prop>
????????????<prop?key="signaturePropFile">org/springside/bookstore/plugins/xfire/wss4j/insecurity_sign.properties</prop>
????????????<prop?key="passwordCallbackClass">org.springside.bookstore.plugins.xfire.wss4j.PasswordHandler</prop>
??????????</props>
????????</property>
????</bean>
????
</beans>

第四,配置insecurity_enc.properties和insecurity_sign.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=SpringSide
org.apache.ws.security.crypto.merlin.alias.password=SpringSide
org.apache.ws.security.crypto.merlin.keystore.alias=david
org.apache.ws.security.crypto.merlin.file=org/springside/bookstore/plugins/xfire/wss4j/springside_private.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=SpringSide
org.apache.ws.security.crypto.merlin.keystore.alias=david
org.apache.ws.security.crypto.merlin.file=org/springside/bookstore/plugins/xfire/wss4j/springside_public.jks 第五,使用SecureX生成了兩個keystore文件
springside_private.jks
別名名稱:?david
創建日期:?2006-8-6
輸入類型:KeyEntry
認證鏈長度:?1
認證?[1]:
Owner:?CN=david,?OU=SpringSide,?O=org,?L=gz,?ST=gd,?C=cn
發照者:?CN=david,?OU=SpringSide,?O=org,?L=gz,?ST=gd,?C=cn
序號:?44d4cdcd
有效期間:?Sun?Aug?06?00:56:45?CST?2006?至:?Mon?Aug?06?00:56:45?CST?2007
認證指紋:
?????????MD5:??CF:97:13:0C:70:D0:4D:B6:B4:27:0F:1A:0B:CF:D9:F2
?????????SHA1:?8E:8E:E8:BC:64:39:C8:43:E4:F7:1B:3B:CE:48:1D:6B:A0:2B:58:B5 springside_public.jks
別名名稱:?david
創建日期:?2006-8-6
輸入類型:?trustedCertEntry

Owner:?CN=david,?OU=SpringSide,?O=org,?L=gz,?ST=gd,?C=cn
發照者:?CN=david,?OU=SpringSide,?O=org,?L=gz,?ST=gd,?C=cn
序號:?44d4cdcd
有效期間:?Sun?Aug?06?00:56:45?CST?2006?至:?Mon?Aug?06?00:56:45?CST?2007
認證指紋:
?????????MD5:??CF:97:13:0C:70:D0:4D:B6:B4:27:0F:1A:0B:CF:D9:F2
?????????SHA1:?8E:8E:E8:BC:64:39:C8:43:E4:F7:1B:3B:CE:48:1D:6B:A0:2B:58:B5第五,新版本SpringSide需要
http://www.bouncycastle.org/download/bcprov-jdk15-133.jar并且要配置java.security
另外,還要使用jdk加密增強策略
http://www.aygfsteel.com/openssl/archive/2006/03/08/34381.html用戶要使用WSS4J,需要配置Bouncycastle這個SecurityProvider,否則
運行Enc模式的XFire認證的時候,會拋出異常:
org.apache.ws.security.WSSecurityException: An unsupported signature or encryption algorithm was used unsupported key
配合java.security也是非常簡單:
在最后加入BouncycastleProvider。
security.provider.1=sun.security.provider.Sun
security.provider.2=com.sun.net.ssl.internal.ssl.Provider
security.provider.3=com.sun.rsajca.Provider
security.provider.4=com.sun.crypto.provider.SunJCE
security.provider.5=sun.security.jgss.SunProvider
security.provider.6=org.bouncycastle.jce.provider.BouncyCastleProvider
[WebService Client端配置]
1,Encrypt模式的Client是在客戶端用david的公鑰加密Soap里面的usernameToken,然后發送到Web服務,Web服務用david的私鑰來驗證。這種模式需要客戶端預先知道服務器端的公鑰。
在Encrypt模式中,需要這樣配置ClientHandler:
????????Service?serviceModel?=?new?ObjectServiceFactory().create(BookServiceWSS4JEnc.class);
????????XFireProxyFactory?factory?=?new?XFireProxyFactory(getXFire());

????????BookService?service?=?(BookService)?factory.create(serviceModel,?"xfire.local://BookServiceWSS4JEnc");

????????Client?client?=?((XFireProxy)?Proxy.getInvocationHandler(service)).getClient();
????????//掛上WSS4JOutHandler,提供認證
????????client.addOutHandler(new?DOMOutHandler());
????????Properties?properties?=?new?Properties();
????????configureOutProperties(properties);
????????client.addOutHandler(new?WSS4JOutHandler(properties));

????????List?list?=?service.getAllCategorys(); configureOutProperties函數負責指定Client使用何種安全策略,沒錯,使用outsecurity_enc.properties,這個properties是跟Server端的insecurity_enc.properties一起使用的。
????protected?void?configureOutProperties(Properties?config)?{
????????config.setProperty(WSHandlerConstants.ACTION,?WSHandlerConstants.ENCRYPT);
????????config.setProperty(WSHandlerConstants.USER,?"david");
????????//config.setProperty(WSHandlerConstants.PW_CALLBACK_CLASS,?PasswordHandler.class.getName());
????????//Configuration?of?public?key?used?to?encrypt?message?goes?to?properties?file.
????????config.setProperty(WSHandlerConstants.ENC_PROP_FILE,
???????????????????????????????"org/springside/bookstore/plugins/xfire/outsecurity_enc.properties");
????}
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=SpringSide
org.apache.ws.security.crypto.merlin.keystore.alias=david
org.apache.ws.security.crypto.merlin.file=org/springside/bookstore/plugins/xfire/wss4j/springside_public.jks
2, Sign模式的Client同樣也是很簡單,這種模式是Client端用自己的私鑰為usernameToken簽名,服務器端用Client的公鑰來驗證簽名,因此,服務器端需要預先知道客戶端的公鑰。
對應于Encrypt模式,這里的configureOutProperties需要這樣來配置:
????protected?void?configureOutProperties(Properties?properties)?{
????????properties.setProperty(WSHandlerConstants.ACTION,WSHandlerConstants.SIGNATURE);
????????//?User?in?keystore
????????properties.setProperty(WSHandlerConstants.USER,?"david");
????????//?This?callback?is?used?to?specify?password?for?given?user?for?keystore
????????properties.setProperty(WSHandlerConstants.PW_CALLBACK_CLASS,?PasswordHandler.class.getName());
????????//?Configuration?for?accessing?private?key?in?keystore
????????properties.setProperty(WSHandlerConstants.SIG_PROP_FILE,"org/springside/bookstore/plugins/xfire/outsecurity_sign.properties");
????????properties.setProperty(WSHandlerConstants.SIG_KEY_ID,"IssuerSerial");
????}
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=SpringSide
org.apache.ws.security.crypto.merlin.alias.password=SpringSide
org.apache.ws.security.crypto.merlin.keystore.alias=david
org.apache.ws.security.crypto.merlin.file=org/springside/bookstore/plugins/xfire/wss4j/springside_private.jks