WebSerice是一种开放的web服务,任何人都可以访问,但我们有时候需要考虑只有付费用户才能使用WS,所以,我们就需要对WS加入安全验证机制,当然,可以利用防火墙的IP过滤,web应用的配置从最外层去隔离非法用户,但在内层,我们也可以使用SOAP Header的方式,由客户端发送验证数据,服务端验通过后基WS访问权限
首先根据我的这篇Blog
http://blog.csdn.net/daryl715/archive/2007/07/25/1707161.aspx
配置WS Server和WS Client,其中Client端的测试代码类名由Client改为ClientTest,因为我们要用到Xfire的一个名为Client的类?
?
首先我们编写服务端验证类继承AbstractHandler
?

package
?test;


import
?org.codehaus.xfire.MessageContext;

import
?org.codehaus.xfire.handler.AbstractHandler;

import
?org.jdom.Element;



public
?
class
?AuthenticationHandler?
extends
?AbstractHandler?
...
{



????public?void?invoke(MessageContext?cfx)?throws?Exception?...{

???????????if(cfx.getInMessage().getHeader()?==?null)


???????????...{

???????????????throw?new?org.codehaus.xfire.fault.XFireFault("请求必须包含验证信息",org.codehaus.xfire.fault.XFireFault.SENDER);

???????????}

???????????Element?token=cfx.getInMessage().getHeader().getChild("AuthenticationToken");

???????????if?(token?==?null)?


???????????...{?

????????????throw?new?org.codehaus.xfire.fault.XFireFault("请求必须包含身份验证信息",?org.codehaus.xfire.fault.XFireFault.SENDER);?

???????????}?


??????????????String?username?=?token.getChild("Username").getValue();?

??????????????String?password?=?token.getChild("Password").getValue();?

??????????????try?


??????????????...{?

??????????????????//进行身份验证?,只有abcd@1234的用户为授权用户

?????????????????if(username.equals("abcd")?&&?password.equals("1234"))

??????????????????//这语句不显示

??????????????????System.out.println("身份验证通过");

?????????????????else?throw?new?Exception();

??????????????}?

??????????????catch?(Exception?e)?


??????????????...{?

??????????????????throw?new???org.codehaus.xfire.fault.XFireFault("非法的用户名和密码",???org.codehaus.xfire.fault.XFireFault.SENDER);?

??????????????}?


??????????}?




}

?
下面是Client发送授权信息
?

package
?test;


import
?org.codehaus.xfire.MessageContext;

import
?org.codehaus.xfire.handler.AbstractHandler;

import
?org.jdom.Element;



public
?
class
?ClientAuthenticationHandler?
extends
?AbstractHandler?
...
{


?????private?String?username?=?null;?


?????private?String?password?=?null;?



?????public?ClientAuthenticationHandler()?...{?


?????}?



?????public?ClientAuthenticationHandler(String?username,String?password)?...{?


?????????this.username?=?username;?


?????????this.password?=?password;?

?????}?



?????public?void?setUsername(String?username)?...{?


?????????this.username?=?username;?


?????}?



?????public?void?setPassword(String?password)?...{?


?????????this.password?=?password;?


?????}?



?????public?void?invoke(MessageContext?context)?throws?Exception?...{?


?????????//为SOAP?Header构造验证信息

?????????Element?el?=?new?Element("header");?

?????????context.getOutMessage().setHeader(el);?

?????????Element?auth?=?new?Element("AuthenticationToken");?

?????????Element?username_el?=?new?Element("Username");?

?????????username_el.addContent(username);?

?????????Element?password_el?=?new?Element("Password");?

?????????password_el.addContent(password);?

?????????auth.addContent(username_el);?

?????????auth.addContent(password_el);?

?????????el.addContent(auth);?

?????}?




}

为ClientTest.java加入以下代码
?XFireProxy proxy = (XFireProxy)Proxy.getInvocationHandler(service);
Client client = proxy.getClient();
client.addOutHandler(new ClientAuthenticationHandler("abcd1","1234"));
等等,还没有完,修改Services.xm为WS绑定Handler
??

<?
xml?version="1.0"?encoding="UTF-8"
?>



<
beans
>

<
service?
xmlns
="http://xfire.codehaus.org/config/1.0"
>

<
name
>
HelloService
</
name
>

<
namespace
>
http://test/HelloService
</
namespace
>

<
serviceClass
>
test.IHelloService
</
serviceClass
>

<
implementationClass
>
test.HelloServiceImpl
</
implementationClass
>

?
<
inHandlers
>
?

?
<
handler??
handlerClass?
="test.AuthenticationHandler"
?
></
handler?
>
?

?
</
inHandlers
>

</
service
>

</
beans
>
这样我们就完成了编码,下面启动tomcat,运行客户端代码,本文为abcd@1234位授权用户,使用abcd@1234,可以正常访问WS,如果用错误帐号,则会有以下异常
?

Exception?in?thread?"main"?org.codehaus.xfire.XFireRuntimeException:?Could?not?invoke?service..?Nested?exception?is?org.codehaus.xfire.fault.XFireFault:?非法的用户名和密码

org.codehaus.xfire.fault.XFireFault:?非法的用户名和密码

????at?org.codehaus.xfire.fault.Soap11FaultSerializer.readMessage(Soap11FaultSerializer.java:31)

????at?org.codehaus.xfire.fault.SoapFaultSerializer.readMessage(SoapFaultSerializer.java:28)

????at?org.codehaus.xfire.soap.handler.ReadHeadersHandler.checkForFault(ReadHeadersHandler.java:111)

????at?org.codehaus.xfire.soap.handler.ReadHeadersHandler.invoke(ReadHeadersHandler.java:67)

????at?org.codehaus.xfire.handler.HandlerPipeline.invoke(HandlerPipeline.java:131)

????at?org.codehaus.xfire.client.Client.onReceive(Client.java:406)

????at?org.codehaus.xfire.transport.http.HttpChannel.sendViaClient(HttpChannel.java:139)

????at?org.codehaus.xfire.transport.http.HttpChannel.send(HttpChannel.java:48)

????at?org.codehaus.xfire.handler.OutMessageSender.invoke(OutMessageSender.java:26)

????at?org.codehaus.xfire.handler.HandlerPipeline.invoke(HandlerPipeline.java:131)

????at?org.codehaus.xfire.client.Invocation.invoke(Invocation.java:79)

????at?org.codehaus.xfire.client.Invocation.invoke(Invocation.java:114)

????at?org.codehaus.xfire.client.Client.invoke(Client.java:336)

????at?org.codehaus.xfire.client.XFireProxy.handleRequest(XFireProxy.java:77)

????at?org.codehaus.xfire.client.XFireProxy.invoke(XFireProxy.java:57)

????at?$Proxy0.getUser(Unknown?Source)

????at?test.ClientTest.main(ClientTest.java:39)

?
如果不在CientTest加以下增加Heade则会有以下异常
?XFireProxy proxy = (XFireProxy)Proxy.getInvocationHandler(service);
Client client = proxy.getClient();
?client.addOutHandler(new ClientAuthenticationHandler("abcd1","1234"));

Exception?in?thread?"main"?org.codehaus.xfire.XFireRuntimeException:?Could?not?invoke?service..?Nested?exception?is?org.codehaus.xfire.fault.XFireFault:?请求必须包含验证信息

org.codehaus.xfire.fault.XFireFault:?请求必须包含验证信息

????at?org.codehaus.xfire.fault.Soap11FaultSerializer.readMessage(Soap11FaultSerializer.java:31)

????at?org.codehaus.xfire.fault.SoapFaultSerializer.readMessage(SoapFaultSerializer.java:28)

????at?org.codehaus.xfire.soap.handler.ReadHeadersHandler.checkForFault(ReadHeadersHandler.java:111)

????at?org.codehaus.xfire.soap.handler.ReadHeadersHandler.invoke(ReadHeadersHandler.java:67)

????at?org.codehaus.xfire.handler.HandlerPipeline.invoke(HandlerPipeline.java:131)

????at?org.codehaus.xfire.client.Client.onReceive(Client.java:406)

????at?org.codehaus.xfire.transport.http.HttpChannel.sendViaClient(HttpChannel.java:139)

????at?org.codehaus.xfire.transport.http.HttpChannel.send(HttpChannel.java:48)

????at?org.codehaus.xfire.handler.OutMessageSender.invoke(OutMessageSender.java:26)

????at?org.codehaus.xfire.handler.HandlerPipeline.invoke(HandlerPipeline.java:131)

????at?org.codehaus.xfire.client.Invocation.invoke(Invocation.java:79)

????at?org.codehaus.xfire.client.Invocation.invoke(Invocation.java:114)

????at?org.codehaus.xfire.client.Client.invoke(Client.java:336)

????at?org.codehaus.xfire.client.XFireProxy.handleRequest(XFireProxy.java:77)

????at?org.codehaus.xfire.client.XFireProxy.invoke(XFireProxy.java:57)

????at?$Proxy0.getUser(Unknown?Source)

????at?test.ClientTest.main(ClientTest.java:35)