您的位置:首页 > 其它

wss4j和axis2实现WS-Security

2010-10-28 16:03 211 查看
一、
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
的公钥

解密服务器端返回来的信息。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: