转自[url]http://hi.baidu.com/zhaopengletter/blog/item/a85945915dcf378ba877a448.html
[/url]
一、 wss4j 简介
Wss4j 是 apache 开发的,标准实现 WS-Security (WebService 安全 ) 的开源项目,它提供了用户名令牌环验证 (UsernameToken) 和传递消息时保证信息的完整性和真实性等一些 WebService 安全保障。
二、环境准备
2.1 开发环境准备
在正式开始前还要去下载一个 rampart-1.1.mar ,下载地址 http://apache.hoxt.com/ws/rampart/1_1/ 。把这个东东放到 WEB-INF\modules 下去
这个东东是在 AXIS2 上实现 WSS4J 必需要的一个组件。把 wss4j 的相关 jar 包导到 lib 下。
三、用 KEYTOOL 生成一对 JKS 文件
首先我们用 keytool 生成一对 JKS 文件, service.jks 和 client.jks 。
service.jks 存放了 service 的私钥和 client 的公钥。
client.jks 存放了 client 的私钥和 service 的公钥。
本人生成的
service.jks 的私钥和公钥 keystore 的密码是 apache
client.jks 的私钥和公钥 keystore 的密码是 apache ,
( 注如果不会用 keytool 请自己看相关资料,我用的是 apache 提供 sample 的文件 )
2.2 搭建 webservice 环境
将 axis2.war 包拷贝到 tomcat 安装目录下的 webapps 目录下。
启动 Tomcat(D:\Tomcat5.5\bin\startup.bat) ,打开浏览器输入并访问 :http://127.0.0.1:8080/axis2 来查看 , 结果如下图,表示 axis2 已经工作正常。
四、建立 web 应用
4.1 编写服务器端代码
首先简单介绍我的 Wss4j 实现 WS-Security 功能 , 很简单就是客户端发送一个字符串,服务器端得到该字符串,同时把字符串在发送给客户端, 首先自己建立一个 web 应用工程 , 这里就以我的 wsc 应用工程为例
在 src 下建一个包 com.neusoft.wss4j.rempart.demo.services 在这里写一个类 SimpleService 作为服务器端
该类的内容是:
package com.neusoft.wss4j.rempart.demo.services;
public class SimpleService
{
public String echo(String arg)
{
return arg;
}
}
这个类的作用就是接收客户端的字符串,并且把该字符串返回给客户端。
这里还有个类,该类是实现 UsernameToken 和传送信息的安全性和完整性的核心,该类被配置在 axis2.xml 和 service.xml 中,从而能得到用户配置的 axis2.xml 中的信息,和服务器端配置的 service.xml 的信息。每当客户端发送请求时,它都要首先通过该类获得访问服务端的权限和获得发送数据所需要的加密密码,然后把数据加密发送给服务器端,如果没有权限则不能把数据发送到服务器端,每当服务器端想要把数据传送到客户端时,也要经过次类获得发送数据所需要的加密密码,然后把数据加密返回给客户端,客户端通过解密获得明文信息。它的内容如下:
package com.neusoft.wss4j.rempart.demo.services;
import org.apache.ws.security.WSPasswordCallback;
import javax.security.auth.callback.Callback;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.callback.UnsupportedCallbackException;
import java.io.IOException;
public class PWCBHandler implements CallbackHandler
{
public void handle(Callback[] callbacks) throws IOException,
UnsupportedCallbackException
{
for (int i = 0; i < callbacks.length; i++)
{
WSPasswordCallback pwcb = (WSPasswordCallback)callbacks[i];
String id = pwcb.getIdentifer();
if("client".equals(id))
{
pwcb.setPassword("apache");
}
else if("service".equals(id))
{
pwcb.setPassword("apache");
}
else
{
throw new UnsupportedCallbackException(callbacks[i],
" 对不起,您不是授权用户,不能访问该 WEB 服务! ");
}
}
}
}
4.2 编写服务器端的描述文件 services.xml
然后写一个解析该服务器类 services.xml 文件该文件的内容如下:
<? xml version = "1.0" encoding = "UTF-8" ?>
< service name = "wsc" >
< operation name = "echo" >
< messageReceiver
class = "org.apache.axis2.rpc.receivers.RPCMessageReceiver" />
</ operation >
< parameter name = "ServiceClass" locked = "false" >
com.neusoft.wss4j.rempart.demo.services.SimpleService
</ parameter >
< module ref = "rampart" />
<parameter name="InflowSecurity">
<action>
<items>Timestamp Signature</items>
<signaturePropFile>
keys/service.properties
</signaturePropFile>
</action>
</parameter>
<parameter name="OutflowSecurity">
<action>
<items>Timestamp Signature</items>
<user>service</user>
<passwordCallbackClass>
com.neusoft.wss4j.rempart.demo.services.PWCBHandler
</passwordCallbackClass>
<signaturePropFile>
keys/service.properties
</signaturePropFile>
<signatureKeyIdentifier>
DirectReference
</signatureKeyIdentifier>
</action>
</parameter>
</ service >
服务器 wsc 中有几个方法就需要配置几个 < operation ></ operation >
echo 为 wsc 服务器类中的方法 。 wsc 为服务的名字也就是后边的打包服务器端 wsc .aar 的名字 。着重看下红色 和粉色 字体部分,红色 这部分是客户端传来信息用数字签名来解密客户端传过来的加密信息本例通过 keys 文件夹下的 service.properties 这个文件找到 service.jks 对信息进行解密,粉色 部分是服务器端把输出向客户端的信息加密用的,本例通过 keys 文件夹下的 service.properties 这个文件找到 service.jks 对信息加密的。
service.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 = apache
org.apache.ws.security.crypto.merlin.file = keys/service.jks
写明了加密文件的类型,文件密码,文件名称。
4.3 生成 .aar 服务包
下边就可以根据一个服务器类 SimpleService 一个 service.xml 打包生成一个 wsc.aar 做为服务器端的程序 。 首先将这个 SimpleService 类打包 , 然后把 service.xml 放在打包后的 MATE-INFO 下边
这样服务器端程序 wsc.aar 就完成了 。 下边把 wsc.aar copy 到 D:\program\Tomcat6.0\webapps\axis2\WEB-INF\services 目录下 ( 这里是以我的机器做为例子的 )
然后重启 tomcat 输入 http://127.0.0.1:8080/axis2/services/listServices
就可以看到我们部署到服务器上的服务了。
4.4 编写模拟第三方测试程序
下面我写一个模拟第三方的程序调用 webservice 的一个例子
在包 com.neusoft.wss4j.rempart.demo.client 中的 Client
它的内容如下 :
package com.neusoft.wss4j.rempart.demo.client;
import java.io.Reader;
import java.io.StringReader;
import org.apache.axiom.om.OMAbstractFactory;
import org.apache.axiom.om.OMElement;
import org.apache.axiom.om.OMFactory;
import org.apache.axiom.om.OMNamespace;
import org.apache.axis2.addressing.EndpointReference;
import org.apache.axis2.client.Options;
import org.apache.axis2.client.ServiceClient;
import org.apache.axis2.context.ConfigurationContext;
import org.apache.axis2.context.ConfigurationContextFactory;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.input.SAXBuilder;
public class Client
{
public static void main(String[] args) throws Exception
{
ConfigurationContext ctx = ConfigurationContextFactory
.createConfigurationContextFromFileSystem(
"D:/eclipse3.2/workspace/wsc/WebRoot/WEB-INF", "D:/eclipse3.2/workspace/wsc/WebRoot/WEB-INF/conf/axis2.xml" );
ServiceClient client = new ServiceClient(ctx, null);
Options options = new Options();
options.setAction(" urn:echo ");
options.setTo(new EndpointReference(
" http://localhost:8080/wsc/services/wsc "));
client.setOptions(options);
OMElement response = client.sendReceive(getPayload(" (*^__^*) 嘻嘻…… " ));
OMElement element = response.getFirstElement();
// 把返回的 OMElement 对象转换为 xml 数据
SAXBuilder builder = new SAXBuilder();
Reader in = new StringReader(element.toString());
Document doc = null;
try
{
doc = builder.build(in);
Element Element = doc.getRootElement();
String aa = Element.getTextTrim();
System.out.println(aa);
}
catch (Exception e)
{
System.out.println(e.getMessage());
}
}
private static OMElement getPayload(String value)
{
OMFactory factory = OMAbstractFactory.getOMFactory();
OMNamespace ns = factory.createOMNamespace(
" http://services.demo.rempart.wss4j.neusoft.com/xsd ","ns1");
OMElement elem = factory.createOMElement(" echo ", ns);
OMElement childElem = factory.createOMElement("param0", null);
childElem.setText(value);
elem.addChild(childElem);
return elem;
}
}
这个测试类就不多说了, 粉色 的部分是需要注意的地方。
还有个客户端的 axis2.xml 需要说明一下
他的主要内容如下只要把这部分粘贴到原来的axis2.xml即可 :
<module ref="rampart" />
<parameter name="OutflowSecurity">
<action>
<items>Timestamp Signature</items>
<user>client</user>
<signaturePropFile>keys/client.properties</signaturePropFile>
<passwordCallbackClass>com.neusoft.wss4j.rempart.demo.services.PWCBHandler</passwordCallbackClass>
<signatureKeyIdentifier>DirectReference</signatureKeyIdentifier>
</action>
</parameter>
<parameter name="InflowSecurity">
<action>
<items>Timestamp Signature</items>
<signaturePropFile>keys/client.properties</signaturePropFile>
</action>
</parameter>
注意一下 红色 的部分他是当客户端向服务器端发送数据时,首先访问 com.neusoft.wss4j.rempart.demo.services.PWCBHandler 这个类,得到访问权限和加密信息的文件密码,然后通过加密信息的文件密码和 keys/client.properties 文件找到加密需要的文件 client.jks 把信息加密发送给服务器端, 粉色 部分是通过 keys/client.properties 文件找到解密需要的文件 client.jks 来解密服务器端返回的加密信息。
Keys 文件下的 client.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 = apache
org.apache.ws.security.crypto.merlin.file = keys/client.jks
五、总 结
整理一下思路
1 客户端发送消息给服务器端 : 如果客户端想请求服务器端首先读取客户端配置文件 axis2.xml 文件,得到访问的用户 <user>client</user> 然后找到 com.neusoft.wss4j.rempart.demo.services.PWCBHandler 类,看用户是否有访问服务的权限,如果有则把 client.jks 文件的密码给用户 client , client 通过密码在 axis2.xml 文件中找到 <signaturePropFile>keys/client.properties</signaturePropFile> 找到 client.properties 文件,在 client.properties 文件中找到 client.jks 文件,使用该文件的 client 私钥 从而实现把传送的信息加密,然后把加密的信息发送到服务器端。
2 服务器端接收客户端发送来的消息 : 服务器端接收到消息,然后读取 service.xml 文件找到 <signaturePropFile>keys/service.properties</signaturePropFile> 从而找到 service.properties 文件,通过该文件找到 service.jks 文件使用该文件的 client 的公钥
解密客户端传送来的信息。
3 服务器端返回信息给客户端 : 获得客户端传送过来的明文信息后,从 service.xml 文件
得到加密的用户 <user>service</user> 通过
<passwordCallbackClass>
com.neusoft.wss4j.rempart.demo.services.PWCBHandler
</passwordCallbackClass>
找到验证类 PWCBHandler 得到加密需要的 service.jks 的加密密码 apache
通过 <signaturePropFile>
keys/service.properties
</signaturePropFile> 找到 service.properties 文件,通过该文件找到 service.jks 文件,通过该文件的 service 的私钥 把需要发送给客户端的信息加密。然后发送给客户端
4 客户端接收服务器端返回的消息 : 客户端端接收到消息,然后读取 axis2.xml 文件找到 <signaturePropFile>keys/service.properties</signaturePropFile> 从而找到 client.properties 文件,通过该文件找到 client.jks 文件使用该文件的 service 的公钥
解密服务器端返回来的信息。
axis加密
猜你喜欢
转载自wanghuanqiu.iteye.com/blog/1552997
今日推荐
周排行