鉴于很多系统需要实施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,或是null。
*/
list getallcategorys();
} 第二,接口扩展,即extend基本的bookservice,在xfire中,不同的wss4j策略需要针对不同的serviceclass,否则
里面的定义会overlap。
public interface bookservicewss4jenc extends bookservice {
}
public interface bookservicewss4jsign extends bookservice {
}
第三,配置spring的applicationcontext文件
<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>
<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>
<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">usernametokenprop>
<prop key="passwordcallbackclass">org.springside.bookstore.plugins.xfire.wss4j.passwordhandlerprop>
props>
property>
bean>
<bean id="validateusertokenhandler" class="org.springside.bookstore.plugins.xfire.wss4j.wss4jtokenhandler"/>
<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">encryptprop>
<prop key="decryptionpropfile">org/springside/bookstore/plugins/xfire/wss4j/insecurity_enc.propertiesprop>
<prop key="passwordcallbackclass">org.springside.bookstore.plugins.xfire.wss4j.passwordhandlerprop>
props>
property>
bean>
<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">signatureprop>
<prop key="signaturepropfile">org/springside/bookstore/plugins/xfire/wss4j/insecurity_sign.propertiesprop>
<prop key="passwordcallbackclass">org.springside.bookstore.plugins.xfire.wss4j.passwordhandlerprop>
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=
org.apache.ws.security.crypto.merlin.alias.password=
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=
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=, o=org, l=gz, st=gd, c=cn
发照者: cn=david, ou=, 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=, o=org, l=gz, st=gd, c=cn
发照者: cn=david, ou=, 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需要
并且要配置java.security
另外,还要使用jdk加密增强策略
用户要使用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=
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=
org.apache.ws.security.crypto.merlin.alias.password=
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