`

Web Service实践——Xfire的ws-security用户名和密码安全验证

阅读更多
一、参照《Web Service实践之——XFire实例,以下面有说明》(本空间的文章)建立一个Xfire的应用;

二、引入的jar包:

xfire-1.2.6的所有jar包(包括xfire-all-1.2.6.jar),下载地址:http://xfire.codehaus.org/Download

wss4j-1.5.8.jar:下载地址:http://ws.apache.org/wss4j/

三、服务器端

1、PasswordHandler类,继承自avax.security.auth.callback.CallbackHandler

package com.channelsoft.hr.wssecurity;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

import javax.security.auth.callback.Callback;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.callback.UnsupportedCallbackException;

import org.apache.ws.security.WSPasswordCallback;

public class PasswordHandler implements CallbackHandler {
    @SuppressWarnings("unchecked")
private Map passwords = new HashMap();

    @SuppressWarnings("unchecked")
public PasswordHandler() {
        passwords.put("server", "serverpass");//服务器端记录的用户名和密码,可以有多个
    }

    public void handle(Callback[] callbacks) throws IOException,//回调接口方法
            UnsupportedCallbackException {
        System.out.println("Handling Password!");
        WSPasswordCallback pc = (WSPasswordCallback) callbacks[0];//获取回调对象
        String id = pc.getIdentifer();//获取用户名
        System.out.println("id:"+id+" ,password:"+(String) passwords.get(id));

String validPw = (String)password.get(id);②-3:获取用户对应的正确密码
②-4:如果是明文密码直接进行判断
if(WSConstants.PASSWORD_TEXT.equals(callback.getPasswordType())){
String pw = callback.getPassword();
if(pw == null || !pw.equalsIgnoreCase(validPw)){
throw new WSSecurityException("password not match");
}
}else{
        pc.setPassword((String) passwords.get(id));//如果是密码摘要,向回调设置正确的密码(明文密码)
    }
}

2、service.xml

<beans xmlns="http://xfire.codehaus.org/config/1.0">
<service>
<name>hrwebservice</name>
<namespace>com.channelsoft.hr</namespace>
<serviceClass>com.channelsoft.hr.webservice.DepartmentAndPersonInfo</serviceClass>
<implementationClass>com.channelsoft.hr.webservice.impl.DepartmentAndPersonInfoImpl</implementationClass>
<inHandlers>
          <handler handlerClass="org.codehaus.xfire.util.dom.DOMInHandler" />
            <bean
                class="org.codehaus.xfire.security.wss4j.WSS4JInHandler" xmlns="">
                <property name="properties">
                    <props>
                       <prop key="action">UsernameToken</prop>//使用用户名与密码进行安全验证
                        <prop key="passwordCallbackClass">
                            com.channelsoft.hr.wssecurity.PasswordHandler//回调类
                        </prop>
                    </props>
                </property>
            </bean>
    </inHandlers>
</service>
</beans>

四、客户端

1、

1、PasswordHandler类,继承自avax.security.auth.callback.CallbackHandler

package com.channelsoft.hr.wssecurity;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

import javax.security.auth.callback.Callback;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.callback.UnsupportedCallbackException;

import org.apache.ws.security.WSPasswordCallback;

public class PasswordHandler implements CallbackHandler {
    @SuppressWarnings("unchecked")
private Map passwords = new HashMap();

    @SuppressWarnings("unchecked")
public PasswordHandler() {
        passwords.put("server", "serverpass");//服务器端记录的用户名和密码,可以有多个
    }

    public void handle(Callback[] callbacks) throws IOException,//回调接口方法
            UnsupportedCallbackException {
        System.out.println("Handling Password!");
        WSPasswordCallback pc = (WSPasswordCallback) callbacks[0];//获取回调对象
        String id = pc.getIdentifer();//获取用户名
        System.out.println("id:"+id+" ,password:"+(String) passwords.get(id));

String validPw = (String)password.get(id);②-3:获取用户对应的正确密码
②-4:如果是明文密码直接进行判断
if(WSConstants.PASSWORD_TEXT.equals(callback.getPasswordType())){
String pw = callback.getPassword();
if(pw == null || !pw.equalsIgnoreCase(validPw)){
throw new WSSecurityException("password not match");
}
}else{
        pc.setPassword((String) passwords.get(id));//如果是密码摘要,向回调设置正确的密码(明文密码)
    }
}

2、客户端调用

package hr;

import java.net.MalformedURLException;

import org.codehaus.xfire.client.Client;
import org.codehaus.xfire.client.XFireProxyFactory;
import org.codehaus.xfire.security.wss4j.WSS4JOutHandler;
import org.apache.ws.security.WSConstants;
import org.apache.ws.security.handler.WSHandlerConstants;
import org.codehaus.xfire.service.Service;
import org.codehaus.xfire.service.binding.ObjectServiceFactory;
import org.codehaus.xfire.transport.http.CommonsHttpMessageSender;
import org.codehaus.xfire.util.dom.DOMOutHandler;

import com.channelsoft.hr.webservice.DepartmentAndPersonInfo;

public class getHRInfo
{
public static void main(String args[])
{
   String serviceURL = "http://localhost:8080/HRWebService/services/hrwebservice";
   // 创建service对象
   Service serviceModel = new ObjectServiceFactory().create(DepartmentAndPersonInfo.class);
 
   XFireProxyFactory serviceFactory = new XFireProxyFactory();

   try
   {
    // 获取服务对象
    DepartmentAndPersonInfo service = (DepartmentAndPersonInfo) serviceFactory.create(serviceModel, serviceURL);
  
    // 忽略http连接的超时时间,0为不设置超时时间,》=1为超时毫秒数
    Client client = Client.getInstance(service);
    client.setProperty(CommonsHttpMessageSender.HTTP_TIMEOUT, "0");
    //发送授权信息
//      client.addOutHandler(new ClientAuthenticationHandler("abcd","1234"));


//      //WS-Security
      WSS4JOutHandler wsOut = new WSS4JOutHandler();
      String actions =WSHandlerConstants.USERNAME_TOKEN;
         wsOut.setProperty(WSHandlerConstants.ACTION, actions);//动作
         wsOut.setProperty(WSHandlerConstants.PASSWORD_TYPE, WSConstants.PASSWORD_DIGEST);//密码类型
         wsOut.setProperty(WSHandlerConstants.USER, "server");   //指定用户    
         wsOut.setProperty(WSHandlerConstants.PW_CALLBACK_CLASS, PasswordHandler.class.getName());//密码回调类
       
         client.addOutHandler(new DOMOutHandler());
         client.addOutHandler(wsOut);

      

     
     
    // 调用服务
    String hello = service.queryDepartmentInfo();
    String hello2 = service.queryPersonnelInfo("", "", "");
    System.out.println(hello);
    System.out.println(hello2);

   }
   catch (MalformedURLException e)
   {
    System.out.println("错误!!!");
    e.printStackTrace();
   }
}
}




Web Service实践之——XFire实例


转自:http://www.javaeye.com/topic/195927
1、配置XFire运行环境:
在Tomcat下新建一个Web Applications,命名为stove,然后在其WEB-INF目录下新建一个web.xml文件,文件中输入:

Xml代码
<?xml version="1.0" encoding="GB2312"> 
<!DOCTYPE web-app  
     PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"  
     "http://java.sun.com/dtd/web-app_2_3.dtd"> 
      
<web-app> 
 
  <servlet> 
    <servlet-name>XFireServlet</servlet-name> 
    <display-name>XFire Servlet</display-name> 
    <servlet-class>org.codehaus.xfire.transport.http.XFireConfigurableServlet</servlet-class> 
  </servlet> 
 
  <servlet-mapping> 
    <servlet-name>XFireServlet</servlet-name> 
    <url-pattern>/servlet/XFireServlet/*</url-pattern> 
  </servlet-mapping> 
 
  <servlet-mapping> 
    <servlet-name>XFireServlet</servlet-name> 
    <url-pattern>/services/*</url-pattern> 
  </servlet-mapping> 
 
</web-app> 
其中主要就是引入了XFireServlet,用以处理Web Service请求,并且负责提供Web Service的WSDL,如果你发布了一个名为BookService的WebService,则可以通过网址:
http://<服务器>[:端口]/<webapp名>/services/BookService
来访问这个WebService,并且通过地址:
http://<服务器>[:端口]/<webapp名>/services/BookService?WSDL 来得到这个WebService的WSDL信息。

2、开发最简单的WebService

建一个package:cn.com.pansky.webservice.xfire.study,在这个包下面新建一个接口:

Java代码
package cn.com.pansky.webservice.xfire.study;  
 
public interface SayHiService{  
  public String sayHi(String name);  

这个接口是告诉服务器你的WebService哪些方法可以被用户调用的。下面我们再来写一个SayHiService的实现类,以完成业务逻辑:

Java代码
package cn.com.pansky.webservice.xfire.study;  
 
public class SayHiServiceImpl implements SayHiService{  
  public String sayHi(String name){  
    if(name==null){  
      return "连名字也不肯告诉我吗?";  
     }  
    return name+", 你吃了吗?没吃回家吃去吧。";  
   }  
 
  public String 不告诉你(){  
    return "我的名字不告诉你!";  
   }  
}   这个类实现了sayHi方法,该方法是可以通过WebService调用访问到的。另外还实现了一个方法“不告诉你”,该方法因为没有在接口SayHiService中定义,所以不能被WebService调用到。
   这个例子足够简单吧,就跟我们刚学Java时写的"Hello world"没什么两样。
到这里为止,我们做的跟平时的Java开发没啥区别,该如何来发布WebService呢?
3、把JAVA类发布为WebService:
在src目录下新建文件夹:META-INF/xfire,然后在该文件夹下新建一个XML文件:services.xml,文件内容如下:

Xml代码
<beans xmlns="http://xfire.codehaus.org/config/1.0"> 
  <service> 
    <name>SayHiService</name> 
    <namespace>http://cn.com.pansky/SayHiService</namespace> 
    <serviceClass>cn.com.pansky.webservice.xfire.study.SayHiService</serviceClass> 
    <implementationClass>cn.com.pansky.webservice.xfire.study.SayHiServiceImpl</implementationClass> 
  </service> 
</beans> 
这个文件定义一个WebService: SayHiService,并同时定义了接口和实现类。
好了,该建的文件基本建完了,现在想办法把src下的java文件编译成class,并复制到WEB-INF/classes目录下

4、启动Tomcat,测试WebService
如果Tomcat还没配置好,抽两分钟再配一下。再把Tomcat启动起来。
再打开浏览器,输入:
http://localhost/stove/services
,服务器返回的结果如下:
Available Services:
    * SayHiService [wsdl]
     Generated by XFire ( http://xfire.codehaus.org )
我们看到我们的WebService已经布署成功了,我们再看看它的WSDL信息:

这个文件跟我们用Axis生成的基本是一样的。
5、享受美味的时刻

注意:客户端使用WebService接口需要jar包(wsdl4j-1.6.1.jar和xfire-all-1.2.6.jar),缺少wsdl4j-1.6.1.jar时,会出现错误:The type javax.wsdl.Definition cannot be resolved. It is indirectly referenced from   required .class files


WebService这道大餐算是烹制好了,现在是享用美餐的时候了。
我们写一个客户端吃掉这道大餐:

Java代码
package cn.com.pansky.webservice.xfire.study;  
 
import java.net.MalformedURLException;  
import java.util.Map;  
 
import org.codehaus.xfire.client.Client;  
import org.codehaus.xfire.client.XFireProxyFactory;  
import org.codehaus.xfire.service.Service;  
import org.codehaus.xfire.service.binding.ObjectServiceFactory;  
import org.codehaus.xfire.transport.http.CommonsHttpMessageSender;  
 
public class SayHiClient{  
  public static void main(String args[]) {  
     String serviceURL = "http://localhost/stove/services/SayHiService";  
     Service serviceModel = new ObjectServiceFactory().create(SayHiService.class,null,"http://cn.com.pansky/SayHiService",null);  
 
     XFireProxyFactory serviceFactory = new XFireProxyFactory();  
 
    try{  
       SayHiService service = (SayHiService) serviceFactory.create(serviceModel, serviceURL);  
     
       //忽略http连接的超时时间,0为不设置超时时间,》=1为超时毫秒数
      Client client = Client.getInstance(service);  
       client.setProperty(CommonsHttpMessageSender.HTTP_TIMEOUT, "0");  
 
       String hello = service.sayHi("张山疯");  
       System.out.println("服务器对[张山疯] 的回答是:" + hello );  
 
       hello = service.sayHi(null);  
       System.out.println("服务器胡言乱语说:" + hello );  
 
     } catch (MalformedURLException e) {  
       e.printStackTrace();  
     }  
   }  

注意:当客户端设置http连接超时为1毫秒时

Client client = Client.getInstance(service);   

client.setProperty(CommonsHttpMessageSender.HTTP_TIMEOUT, "1");  

会出现如下错误提示:

log4j:WARN No appenders could be found for logger (org.codehaus.xfire.transport.DefaultTransportManager).
log4j:WARN Please initialize the log4j system properly.
Exception in thread "main" org.codehaus.xfire.XFireRuntimeException: Could not invoke service.. Nested exception is org.codehaus.xfire.fault.XFireFault: Couldn't send message.
org.codehaus.xfire.fault.XFireFault: Couldn't send message.
at org.codehaus.xfire.fault.XFireFault.createFault(XFireFault.java:89)
at org.codehaus.xfire.handler.OutMessageSender.invoke(OutMessageSender.java:30)
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.startSLEEChannel(Unknown Source)
at slee.startSlee.main(startSlee.java:33)
Caused by: org.codehaus.xfire.XFireException: Couldn't send message.
at org.codehaus.xfire.transport.http.HttpChannel.sendViaClient(HttpChannel.java:145)
at org.codehaus.xfire.transport.http.HttpChannel.send(HttpChannel.java:48)
at org.codehaus.xfire.handler.OutMessageSender.invoke(OutMessageSender.java:26)
... 8 more
Caused by: java.net.SocketTimeoutException: Read timed out
at java.net.SocketInputStream.socketRead0(Native Method)
at java.net.SocketInputStream.read(SocketInputStream.java:129)
at java.io.BufferedInputStream.fill(BufferedInputStream.java:218)
at java.io.BufferedInputStream.read(BufferedInputStream.java:237)
at org.apache.commons.httpclient.HttpParser.readRawLine(HttpParser.java:78)
at org.apache.commons.httpclient.HttpParser.readLine(HttpParser.java:106)
at org.apache.commons.httpclient.HttpConnection.readLine(HttpConnection.java:1116)
at org.apache.commons.httpclient.MultiThreadedHttpConnectionManager$HttpConnectionAdapter.readLine(MultiThreadedHttpConnectionManager.java:1413)
at org.apache.commons.httpclient.HttpMethodBase.readStatusLine(HttpMethodBase.java:1973)
at org.apache.commons.httpclient.HttpMethodBase.readResponse(HttpMethodBase.java:1735)
at org.apache.commons.httpclient.HttpMethodBase.execute(HttpMethodBase.java:1098)
at org.apache.commons.httpclient.HttpMethodDirector.executeWithRetry(HttpMethodDirector.java:398)
at org.apache.commons.httpclient.HttpMethodDirector.executeMethod(HttpMethodDirector.java:171)
at org.apache.commons.httpclient.HttpClient.executeMethod(HttpClient.java:397)
at org.codehaus.xfire.transport.http.CommonsHttpMessageSender.send(CommonsHttpMessageSender.java:369)
at org.codehaus.xfire.transport.http.HttpChannel.sendViaClient(HttpChannel.java:123)
... 10 more


分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics