AXIS完全总结

soap协议解析href multiRef 格式数据 上游报文格式变更,没办法,时间紧,手写一版,写死先凑合用,哪位有更好解决方案欢迎指导交流 由<updateType xsi:type="int">2</updateType > 变更为 <updateType href="#id2"/> <multiRef id="id2" soapenc:root="0" soapenv:en 阅读详情

AXIS完全总结

关键词: AXIS        

目录

1.发布web服务

2.发布Web服务使用Handler来增强Web服务的功能

3.建立安全的AXIS服务(上)

4.建立安全的AXIS服务(下)

5.在AXIS服务间传递JavaBean及其安全解决

                          

AXIS学习笔记(一) 
ronghao100 原创

 

前天头告诉我用SOAP WEB服务开发一个客户程序,用来与企业内部的ERP进行交互。晚上赶快找相关的资料猛看,总算对SOAP有了一定的认识。干程序员这行真不容易,好象得不停地学习新东西,一不小心就被淘汰:(不过学习也是个很有意思的事情。好了,废话少说,让我们开始吧。

一、软件环境

1、axis-1_2 (从apache网站下载最新axis-bin-1_2.zip解压即可)

2、Tomcat5.0 

3、JDK5.0

二、相关配置

1、在你的%TOMCAT_HOME%/common/lib下需要加入三个包 activation.jar、mail.jar、tools.jar

2、环境变量设置

  AXIS_HOME 即axis-bin-1_2.zip解压的目录(我的是在F:/soap/axis-1_2)

  AXIS_LIB   即 %AXIS_HOME%/lib

  AXISCLASSPATH 即 %AXIS_LIB%/axis.jar;%AXIS_LIB%/commons-discovery-0.2.jar;%AXIS_LIB%/commons-logging-1.0.4.jar;%AXIS_LIB%/jaxrpc.jar;%AXIS_LIB%/saaj.jar;%AXIS_LIB%/log4j-1.2.8.jar;也就是把%AXIS_LIB%下所用JAR文件都导入

三、实验一下

  在%AXIS_HOME%/webapps下找到axis文件夹,将其整个拷贝到%TOMCAT_HOME%/webapps下,启动

Tomcat,打开浏览器访问http://localhost:8080/axis/,出现以下页面说明你配置成功了。很简单吧:)


四、发布我们的第一个程序

  第一个程序简单的返回HELLO WORLD!

HelloWorld.java

public class HelloWorld {
public String sayHello()
{
  return "HELLO WORLD!"; 
} 
}

我们的第一种发布方式:

将HelloWorld.java拷贝到%TOMCAT_HOME%/webapps/axis下,然后将其改名为HelloWorld.jws,这样AXIS就自然将其发布了。现在写个客户端程序访问一下:

TestClient.java

import org.apache.axis.client.Call;
import org.apache.axis.client.Service;

import javax.xml.rpc.ParameterMode;

public class TestClient
{
  public static void main(String [] args) throws Exception {
    
    String endpoint = "http://localhost:" +"8080"+ "/axis/HelloWorld.jws";//指明服务所在位置

    Service service = new Service(); //创建一个Service实例,注意是必须的!
    Call   call   = (Call) service.createCall();//创建Call实例,也是必须的!

  call.setTargetEndpointAddress( new java.net.URL(endpoint) );//为Call设置服务的位置

    call.setOperationName( "sayHello" );//注意方法名与HelloWorld.java中一样!!

      String res = (String) call.invoke( new Object[] {} );//返回String,没有传入参数

                System.out.println( res );
  }
}

我的测试是在jbuilder2005中,注意项目中要导入其自带的AXIS包(当然应该把其中JAR文件替换一下),可以看到程序返回了 "HELLO WORLD!"

可以看到在AXIS里发布服务其实是一件很容易的事,这是因为这个服务很简单的原因:)下面我们介绍第二种发布方式,这是常用的。

我们的第二种发布方式:

1、将HelloWorld.java编译成HelloWorld.class,放到%TOMCAT_HOME%/webapps/axis/WEB-INF/classes

    下

2、在%TOMCAT_HOME%/webapps/axis/WEB-INF下新建deploy.wsdd文件,即SOAP服务发布描述文件

  deploy.wsdd

<deployment xmlns="http://xml.apache.org/axis/wsdd/" xmlns:java="" target="_blank">http://xml.apache.org/axis/wsdd/providers/java">
  <service name="HelloWorld" provider="java:RPC">
    <parameter name="className" value="HelloWorld"/>
    <parameter name="allowedMethods" value="sayHello"/>
  </service>
</deployment>

在DOS下转换目录到%TOMCAT_HOME%/webapps/axis/WEB-INF,命令:

java -cp %AXISCLASSPATH% org.apache.axis.client.AdminClient deploy.wsdd

你会发现目录下多了一个server-config.wsdd文件,这就是AXIS的配置文件,以后所有的服务发布描述都会在里面找到。(当然,你可以直接修改它,不用再写deploy.wsdd)然后打开浏览器http://localhost:8080/axis/servlet/AxisServlet,你就会看到你的服务已发布

注意:可以直接写server-config.wsdd,如下:

<deployment xmlns="http://xml.apache.org/axis/wsdd/" xmlns:java="http://xml.apache.org/axis/wsdd/providers/java">
<handler type="java:org.apache.axis.handlers.http.URLMapper" name="URLMapper"/>   
   <service name="myService" provider="java:RPC">
        <parameter name="className" value="com.service.myService"/>
        <parameter name="allowedMethods" value="getusername"/>
    </service>
<transport name="http">
 <requestFlow>
    <handler type="URLMapper"/>
 </requestFlow>
</transport>
</deployment>

同样用客户端程序访问一下:(注意和上边的差别!!)

HelloClient.java

import org.apache.axis.client.Call;
import org.apache.axis.client.Service;

public class HelloClient
{
  public static void main(String [] args) throws Exception {

    String endpoint = "http://localhost:" +"8080"+ "/axis/services/HelloWorld";//注意!差别仅仅在这里!!

    Service service = new Service();
    Call   call   = (Call) service.createCall();
    call.setTargetEndpointAddress( new java.net.URL(endpoint) );
    call.setOperationName("sayHello" );

      String res = (String) call.invoke( new Object[] {} );

                System.out.println( res );
  }
}

好了,相信你对AXIS已有了大致的了解。接下来将会涉及到传参数、JAVABEAN对象,及AXIS的安全问题,下次再说吧:)也欢迎和我,一个快乐的JAVA程序员,联系:)ronghao100@hotmail.com 

第三种方式:

 1、编写服务端程序server,SayHello.java,编译server.SayHello.java

package server;

public class SayHello

{

    public String getName(String name)

    {

        return "hello "+name;

    }

}

  2、编写wsdd文件

  deploy.wsdd文件内容如下:

<deployment xmlns="http://xml.apache.org/axis/wsdd/" xmlns:java="http://xml.apache.org/axis/wsdd/providers/java">

 <service provider="java:RPC">

  <parameter value="server.SayHello.getName"/>

  <parameter value="*"/>

 </service>

</deployment>

  3、发布服务:

  编辑一个deploy.bat,Axis_Lib为axis.jar路径。内容如下:

set Axis_Lib=D:/workspace/test/WEB-INF/lib

set Java_Cmd=java -Djava.ext.dirs=%Axis_Lib%

set Axis_Servlet=http://localhost:8080/test/servlet/AxisServlet

%Java_Cmd% org.apache.axis.client.AdminClient -l%Axis_Servlet% deploy.wsdd

  执行这个批处理文件,这时候,如果提示成功的话,访问http://localhost:8080/test/services 就会显示服务列表。

  4、生成客户端client stub文件

  在浏览器上访问服务器端的服务,可以下载到WSDL文件,通过Axis的相关工具,可以自动从WSDL文件中生成Web Service的客户端代码。

  编写一个WSDL2Java.bat文件,其内容如下:

set Axis_Lib=D:/workspace/test/WEB-INF/lib

set Java_Cmd=java -Djava.ext.dirs=%Axis_Lib%

set Output_Path=D:/workspace/test/src

set Package=server.SayHello

%Java_Cmd% org.apache.axis.wsdl.WSDL2Java -o%Output_Path% -p%Package% SayHello.wsdl

  执行这个批处理文件就可以生成client stub.

  生成的stub client文件列表为:SayHello.java,SayHelloService.java,SayHelloServiceLocator.java,SayHelloSoapBindingStub.java .

  5、编写客户端程序,编译并执行

  下面是一段junit测试客户端代码。

import java.net.URL;

import junit.framework.Test;

import junit.framework.TestCase;

import junit.framework.TestSuite;

public class TestWSClient extends TestCase {

    public TestWSClient(String string) {

        super(string);

    }

    public void SayHelloClient() throws Exception {

        SayHelloService service = new SayHelloServiceLocator();

        SayHello_PortType client = service.getSayHello() ;

        String retValue = client.getName("clientname");

        System.out.println(retValue);

    }

    public static Test suite() {

        TestSuite suite = new TestSuite();

        suite.addTest(new TestWSClient("SayHelloClient"));

        return suite;

    }

}


 

++++++++++++++++++++++++++++++++++++++
AXIS学习笔记(二)使用Handler来增强Web服务的功能

Handler的基本概念
J2EE Web 服务中的Handler技术特点非常像Servlet技术中的Filter。我们知道,在Servlet中,当一个HTTP到达服务端时,往往要经过多个Filter对请求进行过滤,然后才到达提供服务的Servlet,这些Filter的功能往往是对请求进行统一编码,对用户进行认证,把用户的访问写入系统日志等。相应的,Web服务中的Handler通常也提供一下的功能: 

对客户端进行认证、授权; 
把用户的访问写入系统日志; 
对请求的SOAP消息进行加密,解密; 
为Web Services对象做缓存。 
SOAP消息Handler能够访问代表RPC请求或者响应的SOAP消息。在JAX-RPC技术中,SOAP消息Handler可以部署在服务端,也可以在客户端使用。 

下面我们来看一个典型的SOAP消息Handler处理顺序: 
某个在线支付服务需要防止非授权的用户访问或者撰改服务端和客户端传输的信息,从而使用消息摘要(Message Digest)的方法对请求和响应的SOAP消息进行加密。当客户端发送SOAP消⑹保?突Ф说?andler把请求消息中的某些敏感的信息(如信用卡密码)进行加密,然后把加密后的SOAP消息传输到服务端;服务端的SOAP消息Handler截取客户端的请求,把请求的SOAP 消息进行解密,然后把解密后的SOAP消息派发到目标的Web服务端点。 

Apache axis是我们当前开发Web服务的较好的选择,使用axisWeb服务开发工具,可以使用Handler来对服务端的请求和响应进行处理。典型的情况下,请求传递如图1所示。 

 


图1 SOAP消息的传递顺序


在图中,轴心点(pivot point)是Apache与提供程序功能相当的部分,通过它来和目标的Web服务进行交互,它通常称为Provider。axis中常用的Provider有Java:RPC,java:MSG,java:EJB。一个Web服务可以部署一个或者多个Handler。 

Apache axis中的Handler体系结构和JAX-RPC 1.0(JSR101)中的体系结构稍有不同,需要声明的是,本文的代码在axis中开发,故需要在axis环境下运行。 

在axis环境下,SOAP消息Handler必须实现org.apache.axis.Handler接口(在JAX-RPC 1.0规范中,SOAP消息Handler必须实现javax.xml.rpc.handler.Handler接口),org.apache.axis.Handler接口的部分代码如下: 

例程1 org.apache.axis.Handle的部分代码


public interface Handler extends Serializable {
  public void init(); 
  public void cleanup();
  public void invoke(MessageContext msgContext) throws AxisFault ;

  public void onFault(MessageContext msgContext);
  public void setOption(String name, Object value);   
  public Object getOption(String name);
  
  public void setName(String name);   
  public String getName();   
  public Element getDeploymentData(Document doc);
  public void generateWSDL(MessageContext msgContext) throws AxisFault;
  …
}

 

为了提供开发的方便,在编写Handler时,只要继承org.apache.axis.handlers. BasicHandler即可,BasicHandler是Handler的一个模板,我们看它的部分代码: 

例程2 BasicHandler的部分代码


public abstract class BasicHandler implements Handler {
  protected static Log log =
    LogFactory.getLog(BasicHandler.class.getName());
  protected Hashtable options;
  protected String name;
  //这个方法必须在Handler中实现。
public abstract void invoke(MessageContext msgContext) throws AxisFault;
public void setOption(String name, Object value) {
    if ( options == null ) initHashtable();
    options.put( name, value );
  }
…
}

 

BasicHandler中的(MessageContext msgContext)方法是Handler实现类必须实现的方法,它通过MessageContext来获得请求或者响应的SOAPMessage对象,然后对SOAPMessage进行处理。 

在介绍Handler的开发之前,我们先来看一下目标Web服务的端点实现类的代码,如例程3所示。 

例程3 目标Web服务的端点实现类


package com.hellking.webservice;
public class HandleredService 
{
//一个简单的Web服务
public String publicMethod(String name)
{
return "Hello!"+name;
}
}
//另一个Web服务端点:
package com.hellking.webservice;
public class OrderService 
{
    //web服务方法:获得客户端的订单信息,并且对订单信息进行对应的处理,
通常情况是把订单的信息写入数据库,然后可客户端返回确认信息。
public String orderProduct(String name,String address,String item,int quantity,Card card)
{
String cardId=card.getCardId();
String cardType=card.getCardType();
String password=card.getPassword();
String rderInfo="name="+name+",address="+address+",item="+item+",quantity="+quantity+"
,cardId="+cardId+",cardType="+cardType+",password="+password;
System.out.println("这里是客户端发送来的信息:");
System.out.println(orderInfo); 
return orderInfo;
} 
}

 

下面我们分不同情况讨论Handler的使用实例。

使用Handler为系统做日志

Handler为系统做日志是一种比较常见而且简单的使用方式。和Servlet中的Filter一样,我们可以使用Handler来把用户的访问写入系统日志。下面我们来看日志Handler的具体代码,如例程4所示。 

例程4 LogHandler的代码


package com.hellking.webservice;

import java.io.FileOutputStream;
import java.io.PrintWriter;
import java.util.Date;

import org.apache.axis.AxisFault;
import org.apache.axis.Handler;
import org.apache.axis.MessageContext;
import org.apache.axis.handlers.BasicHandler;

public class LogHandler extends BasicHandler {

  /**invoke,每一个handler都必须实现的方法。
*/
  public void invoke(MessageContext msgContext) throws AxisFault
  {
    //每当web服务被调用,都记录到log中。
    try {
        Handler handler = msgContext.getService();
        String filename = (String)getOption("filename");
        if ((filename == null) || (filename.equals("")))
          throw new AxisFault("Server.NoLogFile",
                      "No log file configured for the LogHandler!",
                        null, null);
        FileOutputStream fos = new FileOutputStream(filename, true);         
        PrintWriter writer = new PrintWriter(fos);         
        Integer counter = (Integer)handler.getOption("accesses");
        if (counter == null)
          counter = new Integer(0);
        
        counter = new Integer(counter.intValue() + 1);         
        Date date = new Date();
        msgContext.getMessage().writeTo(System.out);
      
        String result = "在"+date + ": Web 服务 " +
                  msgContext.getTargetService() +
                  " 被调用,现在已经共调用了 " + counter + " 次.";
        handler.setOption("accesses", counter);         
        writer.println(result);         
        writer.close();
    } catch (Exception e) {
        throw AxisFault.makeFault(e);
    }
  }
}

前面我们说过,Handler实现类必须实现invoke方法,invoke方法是Handler处理其业务的入口点。LogHandler的主要功能是把客户端访问的Web服务的名称和访问时间、访问的次数记录到一个日志文件中。 

下面部署这个前面开发的Web服务对像,然后为Web服务指定Handler。编辑Axis_Home/WEB-INF/ server-config.wsdd文件,在其中加入以下的内容:

<service name="HandleredService" provider="java:RPC">
<parameter name="allowedMethods" value="*"/>
<parameter name="className" value="com.hellking.webservice.HandleredService"/>
<parameter name="allowedRoles" value="chen"/>
<beanMapping languageSpecificType="java:com.hellking.webservice.Card"
qname="card:card" xmlns:card="card"/>
<requestFlow>
<handler name="logging" type="java:com.hellking.webservice.LogHandler">
<parameter name="filename" value="c://MyService.log"/>
</handler>
</requestFlow>
</service>

 


…
</globalConfiguration>
…
<handler name="logging" type="java:com.hellking.webservice.LogHandler">
<parameter name="filename" value="c://MyService.log"/>
</handler>
…
<service name="HandleredService" provider="java:RPC">
…
<requestFlow>
<handler type="logging"/>
  …<!--在这里可以指定多个Handler-->
</requestFlow>
</service>

 


http://127.0.0.1:8080/handler/services/HandleredService?wsdl&method=publicMethod&name=chen

注意:这个URL需要根据具体情况改变。

 

在Sun Jul 06 22:42:03 CST 2003: Web 服务 HandleredService 被调用,现在已经共调用了 1 次.
在Sun Jul 06 22:42:06 CST 2003: Web 服务 HandleredService 被调用,现在已经共调用了 2 次.
在Sun Jul 06 22:42:13 CST 2003: Web 服务 HandleredService 被调用,现在已经共调用了 3 次.

使用Handler对用户的访问认证

使用Handler为用户访问认证也是它的典型使用,通过它,可以减少在Web服务端代码中认证的麻烦,同时可以在部署描述符中灵活改变用户的访问权限。 

对用户认证的Handler代码如下:

例程5 认证的Handler


package com.hellking.webservice;
import….

//此handler的目的是对用户认证,只有认证的用户才能访问目标服务。
public class AuthenticationHandler extends BasicHandler
{
/**invoke,每一个handler都必须实现的方法。
*/
public void invoke(MessageContext msgContext)throws AxisFault
{ 
    SecurityProvider provider = (SecurityProvider)msgContext.getProperty("securityProvider");
if(provider==null)
{
  provider= new SimpleSecurityProvider();
        msgContext.setProperty("securityProvider", provider);
      }
    if(provider!=null)
    {       
      String userId=msgContext.getUsername();
      String password=msgContext.getPassword();
      
      //对用户进行认证,如果authUser==null,表示没有通过认证,
抛出Server.Unauthenticated异常。
        org.apache.axis.security.AuthenticatedUser authUser 
= provider.authenticate(msgContext);
        if(authUser==null)
        throw new AxisFault("Server.Unauthenticated", 
Messages.getMessage("cantAuth01", userId), null,null);
        //用户通过认证,把用户的设置成认证了的用户。
        msgContext.setProperty("authenticatedUser", authUser);
    } 
  }
}

 

在AuthenticationHandler代码里,它从MessageContext中获得用户信息,然后进行认证,如果认证成功,那么就使用msgContext.setProperty("authenticatedUser", authUser)方法把用户设置成认证了的用户,如果认证不成功,那么就抛出Server.Unauthenticated异常。 

部署这个Handler,同样,在server-config里加入以下的内容:

 

<handler name="authen" type="java:com.hellking.webservice.AuthenticationHandler"/>
…
<service name="HandleredService" provider="java:RPC">
<parameter name="allowedRoles" value="chen"/>
…
</service>

WEB-INF/users.lst文件中加入以下用户:

hellking hellking
chen chen

http://127.0.0.1:8080/handler/services/HandleredService?wsdl&method=publicMethod&name=chen

将会提示输入用户名和密码,如图2所示。

图2 访问web服务时的验证 

如果客户端是应用程序,那么可以这样在客户端设置用户名和密码:

例程6 在客户端设置用户名和密码


http://127.0.0.1:808
String endpointURL = "http://127.0.0.1:8080/handler/services/HandleredService?wsdl";         
        Service service = new Service();
        Call   call   = (Call) service.createCall();
        call.setTargetEndpointAddress( new java.net.URL(endpointURL) );
        call.setOperationName( new
QName("HandleredService", "orderProduct") );//设置操作的名称。
        //由于需要认证,故需要设置调用的用户名和密码。
        call.getMessageContext().setUsername("chen");
        call.getMessageContext().setPassword("chen");       

 

使用Handler对用户的访问授权

对于已经认证了的用户,有时在他们操作某个特定的服务时,还需要进行授权,只有授权的用户才能继续进行操作。我们看对用户进行授权的Handler的代码。 

例程7 对用户进行授权的代码


package com.hellking.webservice;

import…

//此handler的目的是对认证的用户授权,只有授权的用户才能访问目标服务。
public class AuthorizationHandler extends BasicHandler
{
/**invoke,每一个handler都必须实现的方法。
*/
public void invoke(MessageContext msgContext)
    throws AxisFault
  {
    
    AuthenticatedUser user = (AuthenticatedUser)msgContext.getProperty("authenticatedUser");
    if(user == null)
        throw new AxisFault("Server.NoUser", Messages.getMessage("needUser00"), null, null);
    String userId = user.getName();
    Handler serviceHandler = msgContext.getService();
    if(serviceHandler == null)
        throw new AxisFault(Messages.getMessage("needService00"));
    String serviceName = serviceHandler.getName();
    String allowedRoles = (String)serviceHandler.getOption("allowedRoles");
    if(allowedRoles == null)
    {       
        return;
    }
    SecurityProvider provider = (SecurityProvider)msgContext.getProperty("securityProvider");
    if(provider == null)
        throw new AxisFault(Messages.getMessage("noSecurity00"));
    for(StringTokenizer st = new StringTokenizer(allowedRoles, ","); st.hasMoreTokens();)
    {
        String thisRole = st.nextToken();
        if(provider.userMatches(user, thisRole))
        {
          return;//访问授权通过。
        }
    }
    //没有通过授权,不能访问目标服务,抛出Server.Unauthorized异常。
    throw new AxisFault("Server.Unauthorized", 
Messages.getMessage("cantAuth02", userId, serviceName), null, null);
  }   
}


在service-config.wsdd文件中,我们为Web服务指定了以下的用户:

<parameter name="allowedRoles" value="chen,hellking"/>


provider.userMatches(user, thisRole)将匹配允许访问Web服务的用户,如果匹配成功,那么授权通过,如果没有授权成功,那么抛出Server.Unauthorized异常。 

使用Handler对SOAP消息进行加密、解密

由于SOAP消息在HTTP协议中传输,而HTTP协议的安全度是比较低的,怎么保证信息安全到达对方而不泄漏或中途被撰改,将是Web服务必须解决的问题。围绕Web服务的安全,有很多相关的技术,比如WS-Security,WS-Trace等,另外,还有以下相关技术: 

XML Digital Signature(XML数字签名) 
XML Encryption (XML加密) 
XKMS (XML Key Management Specification) 
XACML (eXtensible Access Control Markup Language) 
SAML (Secure Assertion Markup Language) 
ebXML Message Service Security 
Identity Management & Liberty Project 
不管使用什么技术,要使信息安全到达对方,必须把它进行加密,然后在对方收到信息后解密。为了提供开发的方便,可以使用Handler技术,在客户端发送信息前,使用客户端的Handler对SOAP消息中的关键信息进行加密;在服务端接收到消息后,有相应的Handler把消息进行解密,然后才把SOAP消息派发到目标服务。 

下面我们来看一个具体的例子。加入使用SOAP消息发送订单的信息,订单的信息如下:

例程8 要发送的订单SOAP消息

<soap-env:Envelope xmlns:soap-env="" target="_blank">http://schemas.xmlsoap.org/soap/envelope/">
  <soap-env:Header/>
  <soapenv:Body>
  <ns1:orderProduct soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encod
ing/" xmlns:ns1="HandleredService">
  <arg0 xsi:type="xsd:string">hellking</arg0>
  <arg1 xsi:type="xsd:string">beijing</arg1>
  <arg2 xsi:type="xsd:string">music-100</arg2>
  <arg3 xsi:type="xsd:int">10</arg3>
  <arg4 href="#id0"/>
  </ns1:orderProduct>
  <multiRef id="id0" soapenc:root="0" soapenv:encodingStyle="http://schemas.xmls
oap.org/soap/encoding/" xsi:type="ns2:card" xmlns:soapenc="http://schemas.xmlsoa
p.org/soap/encoding/" xmlns:ns2="card">
  
    <cardId xsi:type="xsd:string">234230572</cardId>
          
    <cardType xsi:type="xsd:string">visa</cardType>
          
    <password xsi:type="xsd:string">234kdsjf</password>
  </multiRef>
</soapenv:Body>
  </soap-env:Envelope>

    


上面的黑体字是传输的敏感信息,故需要加密。我们可以使用Message Digest之类的方法进行加密。加密之后的信息结构如下: 

例程9 把SOAP消息某些部分加密


<?xml version="1.0" encoding="UTF-8"?>
<soapenv:Envelope …
<soapenv:Body>
<ns1:orderProduct …>
  …
  <arg4 href="#id0"/>
</ns1:orderProduct>
<multiRef …>
  <ns3:EncryptedData xmlns:ns3="" target="_blank">http://www.w3.org/2000/11/temp-xmlenc">
  <ns3:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
  <ns3:DigestValue>rO0ABXQAkyA8Y2FyZ…….
</ns3:DigestValue>
  </ns3:EncryptedData>
</multiRef>
</soapenv:Body>
</soapenv:Envelope>


图3是使用Handler对SOAP消息进行加密、解密后,SOAP消息在传递过程中结构的改变。 


图3 SOAP消息的加密和解密 

从上图可以看出,通过使用加密、解密的Handler,可以确保消息的安全传递。进一步说,如果把这种Handler做成通用的组件,那么就可以灵活地部署到不同的服务端和客户端。 

客户端的Handler的功能是把SOAP消息使用一定的规则加密,假如使用Message Digest加密方式,那么可以这样对敏感的信息加密: 

例程10 对SOAP消息的敏感部分加密


      SOAPElement ele= soapBodyElement.addChildElement(envelope.createName
("EncryptedData","","http://www.w3.org/2000/11/temp-xmlenc")); 
ele.addChildElement("DigestMethod").addAttribute(envelope.createName
("Algorithm"),"http://www.w3.org/2000/09/xmldsig#sha1");
  
  byte[] digest=new byte[100];
  ByteArrayOutputStream out=new ByteArrayOutputStream (100);
  MessageDigest md = MessageDigest.getInstance("SHA");
  ObjectOutputStream oos = new ObjectOutputStream(out);
  //要加密的信息
  String data = " <cardId xsi:type='xsd:string'>234230572
                </cardId><cardType xsi:type='xsd:string'>visa</cardType>
                <password   xsi:type='xsd:string'>234kdsjf</password>";

  byte buf[] = data.getBytes();
  md.update(buf);
  oos.writeObject(data);
  oos.writeObject(md.digest()); 
  digest=out.toByteArray();
  out.close();     
    ele.addChildElement("DigestValue").addTextNode(new 
sun.misc.BASE64Encoder().encode(digest));//对加密的信息编码

 

在客户端发送出SOAP消息时,客户端的Handler拦截发送的SOAP消息,然后对它们进行加密,最后把加密的信息传送到服务端。

服务端接收到加密的信息后,解密的Handler会把对应的加密信息解密。服务端Handler代码如例程11所示。 

例程11 服务端解密Handler


package com.hellking.webservice;
import…
//此handler的目的是把加密的SOAP消息解密成目标服务可以使用的SOAP消息。
public class MessageDigestHandler extends BasicHandler
{
/**invoke,每一个handler都必须实现的方法。
*/
public void invoke(MessageContext msgContext)throws AxisFault
{
try
{   
  //从messageContext例取得SOAPMessage对象。
  SOAPMessage msg=msgContext.getMessage();
  SOAPEnvelope env=msg.getSOAPPart().getEnvelope();
  Iterator it=env.getBody().getChildElements();   
  SOAPElement multi=null;
  while(it.hasNext())
  {
  multi=(SOAPElement)it.next();//multi是soapbody的最后一个child。
  }
  String value="";//value表示加密后的值。
  SOAPElement digestValue=null;
  Iterator it2=multi.getChildElements();
  while(it2.hasNext())
  {
  SOAPElement temp=(SOAPElement)it2.next();
  Iterator it3=temp.getChildElements(env.createName("DigestValue",
"ns3","http://www.w3.org/2000/11/temp-xmlenc"));
  if(it3.hasNext())
  value=((SOAPElement)it3.next()).getValue();//获得加密的值   
  }   
  //把加密的SOAPMessage解密成目标服务可以调用的SOAP消息。
  SOAPMessage   msg2=convertMessage(msg,this.decrypte(value));
  msgContext.setMessage(msg2);     
    }
    catch(Exception e)
    {
    e.printStackTrace();
    }     
} 
//这个方法是把加密的数据进行解密,返回明文。
public String decrypte(String value)
{
String data=null;
try
{
  ByteArrayInputStream fis = new 
ByteArrayInputStream(new sun.misc.BASE64Decoder().decodeBuffer(value));
  ObjectInputStream ois = new ObjectInputStream(fis);
  Object o = ois.readObject();
  if (!(o instanceof String)) {
  System.out.println("Unexpected data in string");
  System.exit(-1);
  }
  data = (String) o;
  System.out.println("解密后的值:" + data);
  o = ois.readObject();
  if (!(o instanceof byte[])) {
  System.out.println("Unexpected data in string");
  System.exit(-1);
  }   
  byte origDigest[] = (byte []) o;
  MessageDigest md = MessageDigest.getInstance("SHA");
  md.update(data.getBytes());
}
      …
return data;
}
  //把解密后的信息重新组装成服务端能够使用的SOAP消息。
public SOAPMessage convertMessage(SOAPMessage msg,String data)
{   
  ….
}
}     

 

可以看出,服务端解密的Handler和客户端加密的Handler的操作是相反的过程。

总结

通过以上的讨论,相信大家已经掌握了Handler的基本使用技巧。可以看出,通过使用Handler,可以给Web服务提供一些额外的功能。在实际的开发中,我们可以开发出一些通用的Handler,然后通过不同的搭配方式把它们部署到不同的Web服务中。 
 
+++++++++++++++++++++++++++++++++++++++
AXIS学习笔记(三)(建立安全的AXIS服务上) 
ronghao100 原创

 在前面的文章中,我们实现了最简单的AXIS服务。现在我们一起来讨论一下Web服务的安全问题。
根据应用的对安全要求的级别不同,可以采用不同的方式来实现安全性,以下是目前最常用的一些实现方式(从低到高排列):
  1、J2EE Web应用默认的访问控制(数据是明文的); 
  2、使用axis的Handler进行访问控制(数据是明文的); 
  3、使用Servlet过滤器(Filter)进行访问控制(数据是明文的); 
  4、使用SSL/HTTPS协议来传输(加密的数据传输协议); 
  5、使用WS-Security规范对信息进行加密与身份认证(数据被加密传输)。
我们仅讨论第2、4、5种实现方式。在此之前我们先来了解一下AXIS自带的一个工具SOAPMonitor。
一、SOAPMonitor的使用
打开http://localhost:8080/axis/进入AXIS的主页面,你会看见:
  SOAPMonitor-[disabled by default for security reasons] ,默认状态下其是不可用的,现在我们就来激活它。
  
1、到目录%TOMCAT_HOME%/webapps/axis下,你会找到SOAPMonitorApplet.java,在命令行中编译它:
    javac -classpath %AXIS_HOME%/lib/axis.jar SOAPMonitorApplet.java
  编译完之后你会看见目录下多了很多CLASS文件,它们的名字是SOAPMonitorApplet*.class

2、在目录%TOMCAT_HOME%/webapps/axis/WEB-INF下打开server-config.wsdd文件,将下面的两部分代码直
  接加入其中相应的位置
  第一部分:
    <handler name="soapmonitor"   type="java:org.apache.axis.handlers.SOAPMonitorHandler">
    <parameter name="wsdlURL"   value="/axis/SOAPMonitorService-impl.wsdl"/>
    <parameter name="namespace"   value="" target="_blank">http://tempuri.org/wsdl/2001/12/SOAPMonitorService-impl.wsdl"/>
    <parameter name="serviceName" value="SOAPMonitorService"/>
    <parameter name="portName" value="Demo"/>
    </handler>
  第二部分:
    <service name="SOAPMonitorService" provider="java:RPC">
    <parameter name="allowedMethods" value="publishMessage"/>
    <parameter name="className"   value="org.apache.axis.monitor.SOAPMonitorService"/>
    <parameter name="scope" value="Application"/>
    </service>

3、选择你要监控的服务
  以上次的HelloWorld服务为例,在server-config.wsdd中你会找到这段代码
  <service name="HelloWorld" provider="java:RPC">
    <parameter name="allowedMethods" value="sayHello"/>
    <parameter name="className" value="HelloWorld"/>
  </service>
  在这段代码中加入以下的代码:
  <requestFlow>
    <handler type="soapmonitor"/>
  </requestFlow>
  <responseFlow>
    <handler type="soapmonitor"/>
  </responseFlow>
  最后的样子是:
  <service name="HelloWorld" provider="java:RPC">
  <requestFlow>
    <handler type="soapmonitor"/>
  </requestFlow>
  <responseFlow>
    <handler type="soapmonitor"/>
  </responseFlow>
  <parameter name="allowedMethods" value="sayHello"/>
  <parameter name="className" value="HelloWorld"/>
  </service>
  这样HelloWorld服务就被监控了
  
4、启动Tomcat,打开http://localhost:8080/axis/SOAPMonitor,你就会看到Applet界面,在
  jbuilder2005中运行我们上次写的客户端程序 TestClient.java。OK!你会在Applet界面看
  见客户端与服务器端互发的XML内容,注意这里是明文!
  
二、使用axis的Handler进行访问控制(对安全要求不高时推荐)
  axis为Web服务的访问控制提供了相关的配置描述符,并且提供了一个访问控制的简单 Handler。默认情况下,你只要在配置描述符中添加用户,然后在Web服务器的部署描述符中自动允许的角色即可。

1、在axis的配置文件users.lst(位于WEB-INF目录下)中添加一个用户,如"ronghao1111",表示
  用户名为ronghao,密码为1111。
  
2、把例HelloWorld的Web服务重新部署(新加的部分已标出)
  <service name="HelloWorld" provider="java:RPC">
  <requestFlow>
    <handler type="soapmonitor"/>
    <handler type="Authenticate"/> //新加的AXIS自带的Handler
  </requestFlow>
  <responseFlow>
    <handler type="soapmonitor"/>
  </responseFlow>
  <parameter name="allowedMethods" value="sayHello"/>
  <parameter name="allowedRoles" value="ronghao"/>   //注意,这里是新加的部分!
  <parameter name="className" value="HelloWorld"/>
  </service>
在这个部署描述符中,指定HelloWorld服务只能被ronghao访问
  
3、修改客户端程序 TestClient.java,增加访问用户名、密码(新加的部分已标出)
  TestClient.java

import org.apache.axis.client.Call;
import org.apache.axis.client.Service;
import javax.xml.rpc.ParameterMode;

public class TestClient
{
  public static void main(String [] args) throws Exception {
  String endpoint = "http://localhost:" +"8080"+ "/axis/HelloWorld";

    Service service = new Service(); 
    Call   call   = (Call) service.createCall();
    call.getMessageContext().setUsername("ronghao");// 用户名。
    call.getMessageContext().setPassword("1111");//   密码
  call.setTargetEndpointAddress( new java.net.URL(endpoint) );

  call.setOperationName( "sayHello" );
  String res = (String) call.invoke( new Object[] {} );

  System.out.println( res );
  }
}
执行TestClient,能够顺利访问Web服务;如果修改用户名或者密码,那么就不能访问 。同样,
你在http://localhost:8080/axis/SOAPMonitor中看到的请求和响应的XML是明文!

三、使用SSL/HTTPS协议来传输
  Web服务也可以使用SSL作为传输协议。虽然JAX-RPC并没有强制规定是否使用SSL协议,但在tomcat
  下使用HTTPS协议。
1、使用JDK自带的工具创建密匙库和信任库。

1)通过使用以下的命令来创建服务器端的密匙库:
  keytool -genkey -alias Server -keystore server.keystore -keyalg RSA
输入keystore密码: changeit
您的名字与姓氏是什么?
[Unknown]: Server
您的组织单位名称是什么?
[Unknown]: ec
您的组织名称是什么?
[Unknown]: ec
您所在的城市或区域名称是什么?
[Unknown]: beijing
您所在的州或省份名称是什么?
[Unknown]: beijing
该单位的两字母国家代码是什么
[Unknown]: CN
CN=Server, OU=ec, O=ec, L=beijing, ST=beijing, C=CN 正确吗?
[否]: y

输入<Server>的主密码
    (如果和 keystore 密码相同,按回车):
  以上命令执行完成后,将获得一个名为server.keystore的密匙库。
  
2)生成客户端的信任库。首先输出RSA证书:
keytool -export -alias Server -file test_axis.cer -storepass changeit -keystore server.keystore
然后把RSA证书输入到一个新的信任库文件中。这个信任库被客户端使用,被用来验证服务器端的身份。
keytool -import -file test_axis.cer -storepass changeit -keystore client.truststore -alias serverkey -noprompt
以上命令执行完成后,将获得一个名为client.truststore的信任库。

3)同理生成客户端的密匙库client.keystore和服务器端的信任库server.truststore.方便起见给出.bat文件
  gen-cer-store.bat内容如下:
  set SERVER_DN="CN=Server, OU=ec, O=ec, L=BEIJINGC, S=BEIJING, C=CN"
  set CLIENT_DN="CN=Client, OU=ec, O=ec, L=BEIJING, S=BEIJING, C=CN"
  set KS_PASS=-storepass changeit
  set KEYINFO=-keyalg RSA

  keytool -genkey -alias Server -dname %SERVER_DN% %KS_PASS% -keystore server.keystore %KEYINFO% -keypass changeit
  keytool -export -alias Server -file test_axis.cer %KS_PASS% -keystore server.keystore
  keytool -import -file test_axis.cer %KS_PASS% -keystore client.truststore -alias serverkey -noprompt

  keytool -genkey -alias Client -dname %CLIENT_DN% %KS_PASS% -keystore client.keystore %KEYINFO% -keypass changeit
  keytool -export -alias Client -file test_axis.cer %KS_PASS% -keystore client.keystore
  keytool -import -file test_axis.cer %KS_PASS% -keystore server.truststore -alias clientkey -noprompt
  
好的,现在我们就有了四个文件:server.keystore,server.truststore,client.keystore,client.truststore

2、更改Tomcat的配置文件(server.xml),增加以下部署描述符:(其实里面有,只是被注释掉了)
    <Connector port="8440" 
          maxThreads="150" minSpareThreads="25" maxSpareThreads="75"
          enableLookups="false" disableUploadTimeout="true"
          acceptCount="100" scheme="https" secure="true"
          clientAuth="true" keystoreFile="f:/server.keystore" keystorePass="changeit"
          truststoreFile="f:/server.truststore" truststorePass="changeit"
          sslProtocol="TLS" />

3、把HelloWorld重新部署一次,在server-config.wsdd中修改如下部署代码。(还原了而已)
  <service name="HelloWorld" provider="java:RPC">
  <requestFlow>
    <handler type="soapmonitor"/>
  </requestFlow>
  <responseFlow>
    <handler type="soapmonitor"/>
  </responseFlow>
  <parameter name="allowedMethods" value="sayHello"/>
  <parameter name="className" value="HelloWorld"/>
  </service>
  
4、修改客户端程序 TestClient.java(修改的部分已标出)

  public class TestClient
{
  public static void main(String [] args) throws Exception {
  String endpoint = "https://localhost:" +"8440"+ "/axis/HelloWorld";//注意区别在这里!https!

    Service service = new Service(); 
    Call   call   = (Call) service.createCall();
  call.setTargetEndpointAddress( new java.net.URL(endpoint) );

  call.setOperationName( "sayHello" );
  String res = (String) call.invoke( new Object[] {} );

  System.out.println( res );
  }
}

5、最后使用命令来执行客户端程序

java -cp %AXISCLASSPATH%
  -Djavax.net.ssl.keyStore=client.keystore 
  -Djavax.net.ssl.keyStorePassword=changeit 
  -Djavax.net.ssl.trustStore=client.truststore 
  TestClient 
 

+++++++++++++++++++++++++++++++++++++++
AXIS学习笔记(四)(建立安全的AXIS服务下) 
ronghao100 原创 

四、使用WS-Security规范对信息进行加密与身份认证
  我们打算用Handler结合WSSecurity实现Web服务安全(Handler的有关内容请参阅AXIS学习笔记(二))
  设想流程:用WSClientRequestHandler.java位于客户端对客户端发出的XML文档进行加密
          WSServerRequestHandler.java位于服务器端对客户端发出的加密后的XML文档进行解密
          WSServerResponseHandler.java位于服务器端对服务器端返回的XML文档进行加密
          WSClientResponseHandler.java位于客户端对服务器端返回的XML文档进行解密
          
1、使用ISNetworks安全提供者,ISNetworks实现了RSA加密、解密算法。
  当然,你也可以使用其它的安全提供者,并且可以使用不同的加密算法。
  ISNetworks相关包ISNetworksProvider.jar。拷贝到%TOMCAT_HOME%   /webapps/axis/WEB-INF/lib
  
2、Trust Services Integration Kit提供了一个WS-Security实现。你可以从http://www.xmltrustcenter.org获得相关库文件,分别是ws-security.jar和tsik.jar。ws-security.jar中包含一个WSSecurity类,我们使用它来对XML进行数字签名和验证,加密与解密。同样拷贝到%TOMCAT_HOME%/webapps/axis/WEB-INF/lib

3、创建密匙库和信任库。(见上文,一模一样!)
  
4、框架结构
  WSClientHandler.java //基类,包含了一些公用方法
  WSClientRequestHandler.java //继承于WSClientHandler.java,调用WSHelper.java对客户端发出的XML文档进行加密
  WSClientResponseHandler.java //继承于WSClientHandler.java,调用WSHelper.java对服务器端返回的XML文档进行解密
  WSServerHandler.java //基类,包含了一些公用方法
  WSServerRequestHandler.java //继承于WSServerHandler.java,调用WSHelper.java对客户端发出的加密后的XML文档进行解密
  WSServerResponseHandler.java//继承于WSServerHandler.java,调用WSHelper.java对服务器端返回的XML文档进行加密
  WSHelper.java //核心类,对SOAP消息签名、加密、解密、身份验证
  MessageConverter.java //帮助类,Document、SOAP消息互相转换

5、具体分析(在此强烈建议看一下tsik.jar的API)
  WSHelper.java 
  public class WSHelper {
    static String PROVIDER="ISNetworks";//JSSE安全提供者。
//添加JSSE安全提供者,你也可以使用其它安全提供者。只要支持DESede算法。这是程序里动态加载还可以在JDK中静态加载
    static
    {
      java.security.Security.addProvider(new com.isnetworks.provider.jce.ISNetworksProvider());
  }
  /**
  *对XML文档进行数字签名。
  */
    public static void sign(Document doc, String keystore, String storetype,
                                String storepass, String alias, String keypass) throws Exception {
          FileInputStream fileInputStream = new FileInputStream(keystore);
          java.security.KeyStore keyStore = java.security.KeyStore.getInstance(storetype);
          keyStore.load(fileInputStream, storepass.toCharArray());
          PrivateKey key = (PrivateKey)keyStore.getKey(alias, keypass.toCharArray());
          X509Certificate cert = (X509Certificate)keyStore.getCertificate(alias);
          SigningKey sk = SigningKeyFactory.makeSigningKey(key);
          KeyInfo ki = new KeyInfo();
          ki.setCertificate(cert);
          WSSecurity wSSecurity = new WSSecurity();//ws-security.jar中包含的WSSecurity类
          wSSecurity.sign(doc, sk, ki);//签名。


    }
  /**
  *对XML文档进行身份验证。
  */
    public static boolean verify(Document doc, String keystore, String storetype,
                                String storepass) throws Exception {
          FileInputStream fileInputStream = new FileInputStream(keystore);
          java.security.KeyStore keyStore = java.security.KeyStore.getInstance(storetype);
          keyStore.load(fileInputStream, storepass.toCharArray());
          TrustVerifier verifier = new X509TrustVerifier(keyStore);
          WSSecurity wSSecurity = new WSSecurity();
          MessageValidity[] resa = wSSecurity.verify(doc, verifier, null,null);
          if (resa.length > 0)
                return resa[0].isValid();
          return false;
    }
  /**
  *对XML文档进行加密。必须有JSSE提供者才能加密。
  */
    public static void encrypt(Document doc, String keystore, String storetype,
                                String storepass, String alias) throws Exception {
          try
          {
          FileInputStream fileInputStream = new FileInputStream(keystore);
          java.security.KeyStore keyStore = java.security.KeyStore.getInstance(storetype);
          keyStore.load(fileInputStream, storepass.toCharArray());
          X509Certificate cert = (X509Certificate)keyStore.getCertificate(alias);
          PublicKey pubk = cert.getPublicKey();
          KeyGenerator keyGenerator = KeyGenerator.getInstance("DESede",PROVIDER);
          keyGenerator.init(168, new SecureRandom());
          SecretKey key = keyGenerator.generateKey();
          KeyInfo ki = new KeyInfo();
          ki.setCertificate(cert);
          WSSecurity wSSecurity = new WSSecurity();
          //加密。
          wSSecurity.encrypt(doc, key, AlgorithmType.TRIPLEDES, pubk, AlgorithmType.RSA1_5, ki);
    }
    catch(Exception e)
    {
          e.printStackTrace();
    }
    }
  /**
  *对文档进行解密。
  */
    public static void decrypt(Document doc, String keystore, String storetype,
                                String storepass, String alias, String keypass) throws Exception {
          FileInputStream fileInputStream = new FileInputStream(keystore);
          java.security.KeyStore keyStore = java.security.KeyStore.getInstance(storetype);
          keyStore.load(fileInputStream, storepass.toCharArray());
          PrivateKey prvk2 = (PrivateKey)keyStore.getKey(alias, keypass.toCharArray());

          WSSecurity wSSecurity = new WSSecurity();
          //解密。

          wSSecurity.decrypt(doc, prvk2, null);
          WsUtils.removeEncryptedKey(doc);//从 WS-Security Header中删除 EncryptedKey 元素
    }

    public static void removeWSSElements(Document doc) throws Exception {
          WsUtils.removeWSSElements(doc);// 删除WSS相关的元素。
    }

}

  WSClientHandler.java
  //继承自org.apache.axis.handlers.BasicHandler即AXIS内在的
  public class WSClientHandler extends BasicHandler{
protected String keyStoreFile ;
protected String keyStoreType ="JKS";//默认
protected String keyStorePassword ;
protected String keyAlias ;
protected String keyEntryPassword ;
protected String trustStoreFile ;
protected String trustStoreType = "JKS";//默认
protected String trustStorePassword ;
protected String certAlias ;

public void setInitialization(String keyStoreFile,String keyStoreType,String keyStorePassword,
          String keyAlias,String keyEntryPassword,String trustStoreFile,
          String trustStoreType,String trustStorePassword,String certAlias){
this.keyStoreFile=keyStoreFile;
this.keyStoreType=keyStoreType;
this.keyStorePassword=keyStorePassword;
this.keyAlias=keyAlias;
this.keyEntryPassword=keyEntryPassword;
this.trustStoreFile=trustStoreFile;
this.trustStoreType=trustStoreType;
this.trustStorePassword=trustStorePassword;
this.certAlias=certAlias;
}
public void setInitialization(String keyStoreFile,String keyStorePassword,
          String keyAlias,String keyEntryPassword,String trustStoreFile,
          String trustStorePassword,String certAlias){
this.keyStoreFile=keyStoreFile;
this.keyStorePassword=keyStorePassword;
this.keyAlias=keyAlias;
this.keyEntryPassword=keyEntryPassword;
this.trustStoreFile=trustStoreFile;
this.trustStorePassword=trustStorePassword;
this.certAlias=certAlias;
}
public void invoke(MessageContext messageContext) throws AxisFault {//在这个方法里对XML文档进行处理
  //do nothing now!
}
public void onFault(MessageContext msgContext) {
  System.out.println("处理错误,这里忽略!");
    }
}

WSClientRequestHandler.java
public class WSClientRequestHandler extends WSClientHandler{
public void invoke(MessageContext messageContext) throws AxisFault {
  try {

  SOAPMessage soapMessage = messageContext.getMessage();
  Document doc = MessageConverter.convertSoapMessageToDocument(soapMessage); //soapMessage转换为Document
  WSHelper.sign(doc, keyStoreFile, keyStoreType,keyStorePassword, keyAlias, keyEntryPassword); //数字签名
  WSHelper.encrypt(doc, trustStoreFile, trustStoreType, trustStorePassword, certAlias); //加密
  soapMessage = MessageConverter.convertDocumentToSOAPMessage(doc); 
//处理后的Document再转换回soapMessage
  messageContext.setMessage(soapMessage);
  } catch (Exception e){
  System.err.println("在处理响应时发生以下错误: " + e);
    e.printStackTrace(); }
    }
} 

WSClientResponseHandler.java
public class WSClientResponseHandler extends WSClientHandler{
public void invoke(MessageContext messageContext) throws AxisFault {
  try {

        SOAPMessage soapMessage = messageContext.getCurrentMessage();
        Document doc = MessageConverter.convertSoapMessageToDocument(soapMessage);

    WSHelper.decrypt(doc, keyStoreFile, keyStoreType,
                  keyStorePassword, keyAlias, keyEntryPassword);//解密

        WSHelper.verify(doc, trustStoreFile, trustStoreType, trustStorePassword);//验证
        WSHelper.removeWSSElements(doc);
        soapMessage = MessageConverter.convertDocumentToSOAPMessage(doc);
        messageContext.setMessage(soapMessage);
  } catch (Exception e){
        e.printStackTrace();
        System.err.println("在处理响应时发生以下错误: " + e);
                }

    }
}   
  
  WSServerHandler.java 
  public class WSServerHandler extends BasicHandler{
protected String keyStoreFile ;
protected String keyStoreType ="JKS";//默认
protected String keyStorePassword ;
protected String keyAlias ;
protected String keyEntryPassword ;
protected String trustStoreFile ;
protected String trustStoreType = "JKS";//默认
protected String trustStorePassword ;
protected String certAlias ;

public void invoke(MessageContext messageContext) throws AxisFault {
  //do nothing now!
}
public void onFault(MessageContext msgContext) {
  System.out.println("处理错误,这里忽略!");
    }
public void init() { //初始化,从配置文件server-config.wsdd中读取属性
  keyStoreFile = (String)getOption("keyStoreFile");
  if(( keyStoreFile== null) )
    System.err.println("Please keyStoreFile configured for the Handler!");
  trustStoreFile = (String)getOption("trustStoreFile");
  if(( trustStoreFile== null) )
  System.err.println("Please trustStoreFile configured for the Handler!");
  keyStorePassword = (String)getOption("keyStorePassword");
  if(( keyStorePassword== null) )
  System.err.println("Please keyStorePassword configured for the Handler!");
  keyAlias = (String)getOption("keyAlias");
  if(( keyAlias== null) )
  System.err.println("Please keyAlias configured for the Handler!");
  keyEntryPassword = (String)getOption("keyEntryPassword");
  if(( keyEntryPassword== null) )
  System.err.println("Please keyEntryPassword configured for the Handler!");
  trustStorePassword = (String)getOption("trustStorePassword");
  if(( trustStorePassword== null) )
  System.err.println("Please trustStorePassword configured for the Handler!");
  certAlias = (String)getOption("certAlias");
  if ((certAlias==null))
    System.err.println("Please certAlias configured for the Handler!");
  if ((getOption("keyStoreType")) != null)
    keyStoreType = (String)getOption("keyStoreType");
  if ((getOption("trustStoreType")) != null)
    trustStoreType = (String)getOption("trustStoreType");
  }
}       
  
  WSServerRequestHandler.java 
  public class WSServerRequestHandler extends WSServerHandler{
public void invoke(MessageContext messageContext) throws AxisFault {
  try {
    SOAPMessage msg = messageContext.getCurrentMessage();
        Document doc = MessageConverter.convertSoapMessageToDocument(msg);
        System.out.println("接收的原始消息:");
      msg.writeTo(System.out);
    WSHelper.decrypt(doc, keyStoreFile, keyStoreType,
                  keyStorePassword, keyAlias, keyEntryPassword);//解密

        WSHelper.verify(doc, trustStoreFile, trustStoreType, trustStorePassword);//验证
        WSHelper.removeWSSElements(doc);
        msg = MessageConverter.convertDocumentToSOAPMessage(doc);
        System.out.println("怀原后的原始消息:");
        msg.writeTo(System.out);
        messageContext.setMessage(msg);
  } catch (Exception e){
        e.printStackTrace();
        System.err.println("在处理响应时发生以下错误: " + e);
                }

    }
}   
  
  WSServerResponseHandler.java
  public class WSServerResponseHandler extends WSServerHandler{
public void invoke(MessageContext messageContext) throws AxisFault {
  try {

  SOAPMessage soapMessage = messageContext.getMessage();
    System.out.println("返回的原始消息:");
      soapMessage.writeTo(System.out);
    Document doc = MessageConverter.convertSoapMessageToDocument(soapMessage);

    WSHelper.sign(doc, keyStoreFile, keyStoreType,
      keyStorePassword, keyAlias, keyEntryPassword);//数字签名
    WSHelper.encrypt(doc, trustStoreFile, trustStoreType,//加密
    trustStorePassword, certAlias);

    soapMessage = MessageConverter.convertDocumentToSOAPMessage(doc);
    System.out.println("返回的加密后的消息:");
    soapMessage.writeTo(System.out);
    messageContext.setMessage(soapMessage);
    } catch (Exception e){
    System.err.println("在处理响应时发生以下错误: " + e);
      e.printStackTrace();
      }

    }
}

6、应用
  为方便使用,把上述文件打包为ws-axis.jar,放入%TOMCAT_HOME%/webapps/axis/WEB-INF/lib
  
  1)把HelloWorld重新部署一次,在server-config.wsdd中修改如下部署代码。
    <service name="HelloWorld" provider="java:RPC">
      <parameter name="allowedMethods" value="*"/>
      <parameter name="className" value="HelloWorld"/>
      <requestFlow>
      <handler type="soapmonitor"/>
      <handler type="java:com.ronghao.WSAxis.WSServerRequestHandler">
        <parameter name="keyStoreFile" value="f:/server.keystore"/>
        <parameter name="trustStoreFile" value="f:/server.truststore"/>
        <parameter name="keyStorePassword" value="changeit"/>
        <parameter name="keyAlias" value="Server"/>
        <parameter name="keyEntryPassword" value="changeit"/>
        <parameter name="trustStorePassword" value="changeit"/>
        <parameter name="certAlias" value="clientkey"/>
      </handler>
    </requestFlow>
    <responseFlow>
      <handler type="soapmonitor"/>
      <handler type="java:com.ronghao.WSAxis.WSServerResponseHandler">
        <parameter name="keyStoreFile" value="f:/server.keystore"/>
        <parameter name="trustStoreFile" value="f:/server.truststore"/>
        <parameter name="keyStorePassword" value="changeit"/>
        <parameter name="keyAlias" value="Server"/>
        <parameter name="keyEntryPassword" value="changeit"/>
        <parameter name="trustStorePassword" value="changeit"/>
        <parameter name="certAlias" value="clientkey"/>
      </handler>
    </responseFlow>
  </service>
  
  2)修改客户端程序 TestClient.java(修改的部分已标出,记着导入ws-axis.jar)
  import javax.xml.namespace.QName;
  import org.apache.axis.client.Call;
  import org.apache.axis.client.Service;
  import com.ronghao.WSAxis.*;
  
  public class WSSClient1
{
  public static void main(String [] args)
  {
    try {
          //服务端的url,需要根据情况更改。
        String endpointURL = "http://localhost:8080/axis/services/HelloWorld";
        Service svc = new Service();

        WSClientHandler handler=new WSClientRequestHandler();
//注意新加的HANDLER
        handler.setInitialization("f:/client.keystore","changeit","Client","changeit",
          "f:/client.truststore","changeit","serverkey");//初始化
        WSClientHandler handlee=new WSClientResponseHandler();
//注意新加的HANDLER
        handlee.setInitialization("f:/client.keystore","changeit","Client","changeit",
          "f:/client.truststore","changeit","serverkey");//初始化
              Call call =(Call)svc.createCall();
              call.setClientHandlers(handler,handlee);//添加Handler
              call.setTargetEndpointAddress(new java.net.URL(endpointURL));
              call.setOperationName(new QName("sayHello"));

              String result = (String) call.invoke( new Object [] {});
              System.out.println("the result"+result);

    } catch (Exception e) {
          e.printStackTrace();
    }
  }


}
  运行的时候http://localhost:8080/axis/SOAPMonitor中看到的请求的XML就已加密!
  
总结
  这里对代码的解释是不够的,很多概念没有提到。建议你最好看tsik.jar和AXIS的API深入了解。另外对ws-axis.jar的加 解密 实现打算运用apache的wss4j,相关网址http://ws.apache.org/ws-fx/wss4j/。不过这个东西也应该够用了暂时。所有的源文件在附件中附件:soapTest.zip(279K) 
 
++++++++++++++++++++++++++++++++++++++
AXIS学习笔记(五)( 在AXIS服务间传递JavaBean及其安全解决) 
ronghao100 原创 
              在AXIS服务间传递JavaBean及其安全解决
这是AXIS学习笔记的最后一篇。在前面我们讨论了最简单的HelloWorld服务,客户端并没有向服务器端
传递参数,现在我们来传传JavaBean。当然,也可以传递你自己定义的JAVA类,但那样你必须自己创建
专门的XML序列化器和反序列化器;而对JavaBean,AXIS提供了现成的序列化器。(有人说:懒惰是程序员最大的美德,我喜欢,所以我就传传JavaBean)

一、服务器端
1、CLASS类两个Order.class,OrderTest.class,位于%TOMCAT_HOME%/webapps/axis/WEB-INF/classes下
  这两个类都直接给出源码,不再说明
  Order.java
  public class Order {
    private String id;
    private String name;
    public void setId(String id){
      this.id=id;
    }
    public String getId(){
      return id;
    }
    public void setName(String name){
        this.name=name;
    }
    public String getName(){
        return name;
    }
    }
    
  OrderTest.java
  public class OrderTest {
    public Order returnOrder(Order order){
    Order newOrder=new Order();
    if(order.getId().equals("1"))
      newOrder.setName("ronghao");
    else newOrder.setName("haorong");
    return newOrder;
    }
  }
  
2、修改服务器端配置文件server-config.wsdd
  在server-config.wsdd中相应位置添加以下代码
<service name="Order" provider="java:RPC">
  <parameter name="allowedMethods" value="returnOrder"/>
  <parameter name="className" value="OrderTest"/>
  <beanMapping languageSpecificType="java:Order" qname="ns1:Order" 
      xmlns:ns1="urn:BeanService"/>
</service>
可以看到和前面的发布服务代码相比仅多了一行代码
  <beanMapping languageSpecificType="java:Order" qname="ns1:Order" 
      xmlns:ns1="urn:BeanService"/>
  languageSpecificType属性指定JavaBean类文件位置,例如:
  languageSpecificType="java:com.ronghao.axis.Order"
  qname属性指定JavaBean类的名字
  其他是固定的。
  
二、客户端
  客户端类文件一个OrderClient.class,代码如下(变化的部分加注释):
  public class OrderClient
{

  public static void main(String args[])
    throws Exception
  {
    String endpoint = "http://localhost:8080/axis/services/Order"; //服务所在位置
    Order order=new Order();   //JavaBean
    order.setId("1");
    Service service = new Service();
    Call call = (Call)service.createCall();
    //注册JavaBean,注意和server-config.wsdd中的配置代码比较
    QName qn = new QName("urn:BeanService", "Order");
    call.registerTypeMapping(Order.class, qn, new BeanSerializerFactory(Order.class, qn), 
                    new BeanDeserializerFactory(Order.class, qn));
    String name="no!";
    try
    {
        call.setTargetEndpointAddress(new URL(endpoint));
        //调用的服务器端方法
        call.setOperationName(new QName("Order", "returnOrder"));
        //设定传入的参数,这里qn即Order.class
        call.addParameter("arg1", qn, ParameterMode.IN);
        //设定返回的参数是Order.class
        call.setReturnType(qn, Order.class);
        Order result = (Order)call.invoke(new Object[] {
          order
        });
        if(result != null)
          name = result.getName();
    }
    catch(Exception e)
    {
        System.err.println(e);
    }
    System.out.println(name);
  }
}
OK!运行一下,就可以看到返回了"ronghao"。

和上一篇文章一样,我们不容许在网络中传递XML是明文,于是需要加密和验证。这里我们继续采用上次所讲的框架。(已打包成ws-axis.jar)

一、修改 服务 器端配置文件server-config.wsdd(和上一文章一模一样!不再罗嗦)
在server-config.wsdd中相应位置添加以下代码
      <requestFlow>
      <handler type="soapmonitor"/>
      <handler type="java:com.ronghao.WSAxis.WSServerRequestHandler">
        <parameter name="keyStoreFile" value="f:/server.keystore"/>
        <parameter name="trustStoreFile" value="f:/server.truststore"/>
        <parameter name="keyStorePassword" value="changeit"/>
        <parameter name="keyAlias" value="Server"/>
        <parameter name="keyEntryPassword" value="changeit"/>
        <parameter name="trustStorePassword" value="changeit"/>
        <parameter name="certAlias" value="clientkey"/>
      </handler>
    </requestFlow>
    <responseFlow>
      <handler type="soapmonitor"/>
      <handler type="java:com.ronghao.WSAxis.WSServerResponseHandler">
        <parameter name="keyStoreFile" value="f:/server.keystore"/>
        <parameter name="trustStoreFile" value="f:/server.truststore"/>
        <parameter name="keyStorePassword" value="changeit"/>
        <parameter name="keyAlias" value="Server"/>
        <parameter name="keyEntryPassword" value="changeit"/>
        <parameter name="trustStorePassword" value="changeit"/>
        <parameter name="certAlias" value="clientkey"/>
      </handler>
    </responseFlow>
    
二、客户端(区别就在这里,注意!!)
首先在这里要说一下,客户端代码编写困扰了我很长一段时间(整整一天),因为它并不象我想象的那么简单,当然解决起来还是挺简单的:)问题的解决经历了三个阶段

第一阶段:
  在这个阶段我想当然的在OrderClient.class中加入了如下代码:
        WSClientHandler handler=new WSClientRequestHandler();//注意新加的HANDLER
        handler.setInitialization("f:/client.keystore","changeit","Client","changeit",
          "f:/client.truststore","changeit","serverkey");//初始化
        WSClientHandler handlee=new WSClientResponseHandler();//注意新加的HANDLER
        handlee.setInitialization("f:/client.keystore","changeit","Client","changeit",
          "f:/client.truststore","changeit","serverkey");//初始化
        call.setClientHandlers(handler,handlee);//添加Handler
  这个方法也是我在上一文章里介绍的,结果抛出以下异常:
  faultString: org.xml.sax.SAXException: Deserializing parameter
  &apos;newProfileReturn&apos;: could not find deserializer for type
  {urn:BeanService Order}SerializableProfile
  也就是说不能正常解析XML文件,于是理所当然的郁闷了,觉得代码中肯定漏设了CALL的一个属性,于是查看AXIS的源代码,没有结果!转机出现在下面一行代码,在不断的抛出异常中我修改了代码
  将call.setClientHandlers(handler,handlee);改为
  call.setClientHandlers(null,null);
  结果程序还是抛出同样的异常,于是意识到这可能是AXIS的一个BUG,为证明这一点,我将下面的Handler初始化代码删除
        WSClientHandler handler=new WSClientRequestHandler();//注意新加的HANDLER
        handler.setInitialization("f:/client.keystore","changeit","Client","changeit",
          "f:/client.truststore","changeit","serverkey");//初始化
        WSClientHandler handlee=new WSClientResponseHandler();//注意新加的HANDLER
        handlee.setInitialization("f:/client.keystore","changeit","Client","changeit",
          "f:/client.truststore","changeit","serverkey");//初始化
  结果还是抛出同样的异常,果然是BUG!得到这个结论后去了apache AXIS主页,在问题列表中见到了完全一样问题的提交,但没有解答(晕!)
  最后得到了结论:call的setClientHandlers()方法只有当call处理简单的数据类型,如String,int等等才能正常使用!
  (当然,如果你对这个问题有不同的见解,欢迎和我联系。或许我错了,但程序不运行是真的:))
  
第二阶段:
  开始在google上找问题的解决方法,这也是我的习惯:)。找了一个类似问题的讨论,地址如下:
  http://marc.theaimsgroup.com/?l=axis-user&m=111259980822735&w=2
  他们的解决方法是Handler继承于javax.xml.rpc.handler.Handler,然后在程序里动态注册而在我的ws-axis.jar里Handler继承于org.apache.axis.handlers.BasicHandler。当然,
  javax.xml.rpc.handler.Handler是org.apache.axis.handlers.BasicHandler的老爸,但在程序里老爸和儿子之间却不能很好的兼容,这也许就是所谓的代沟??无奈中重新写了Handler,但在运行中却抛出异常,提示message在被invoke的时候已被更改。我靠,Handler的作用就是来更改message的啊!这是什么世道!
  我知道很多程序采用的就是这种方法,但我好象怎么修改都抛出上述异常。
  
第三阶段
  既然在程序里动态注册Handler行不通,于是决定写个单独的配置文件来注册Handler。如果这种方法不幸失败就返回第二阶段。好马为什么不吃回头草??
1、ws-axis.jar中修改WSClientHandler.class,修改后如下,我想你一看就明白为何修改

public class WSClientHandler extends BasicHandler{
protected String keyStoreFile ;
protected String keyStoreType ="JKS";
protected String keyStorePassword ;
protected String keyAlias ;
protected String keyEntryPassword ;
protected String trustStoreFile ;
protected String trustStoreType = "JKS";
protected String trustStorePassword ;
protected String certAlias ;

public void init() {
  keyStoreFile = (String)getOption("keyStoreFile");
  if(( keyStoreFile== null) )
    System.err.println("Please keyStoreFile configured for the Handler!");
  trustStoreFile = (String)getOption("trustStoreFile");
  if(( trustStoreFile== null) )
  System.err.println("Please trustStoreFile configured for the Handler!");
  keyStorePassword = (String)getOption("keyStorePassword");
  if(( keyStorePassword== null) )
  System.err.println("Please keyStorePassword configured for the Handler!");
  keyAlias = (String)getOption("keyAlias");
  if(( keyAlias== null) )
  System.err.println("Please keyAlias configured for the Handler!");
  keyEntryPassword = (String)getOption("keyEntryPassword");
  if(( keyEntryPassword== null) )
  System.err.println("Please keyEntryPassword configured for the Handler!");
  trustStorePassword = (String)getOption("trustStorePassword");
  if(( trustStorePassword== null) )
  System.err.println("Please trustStorePassword configured for the Handler!");
  certAlias = (String)getOption("certAlias");
  if ((certAlias==null))
    System.err.println("Please certAlias configured for the Handler!");
  if ((getOption("keyStoreType")) != null)
    keyStoreType = (String)getOption("keyStoreType");
  if ((getOption("trustStoreType")) != null)
    trustStoreType = (String)getOption("trustStoreType");
  }
public void invoke(MessageContext messageContext) throws AxisFault {
  //do nothing now!
}
public void onFault(MessageContext msgContext) {
  System.out.println("处理错误,这里忽略!");
    }
}
  
2、写 客户端 的配置代码client-config.wsdd,如下:
  <?xml version="1.0" encoding="UTF-8"?>
  <deployment name="defaultClientConfig"
    xmlns="http://xml.apache.org/axis/wsdd/"
    xmlns:java="" target="_blank">http://xml.apache.org/axis/wsdd/providers/java">
  <transport name="http"
    pivot="java:org.apache.axis.transport.http.HTTPSender"/>
  <transport name="local"
    pivot="java:org.apache.axis.transport.local.LocalSender"/>
  <transport name="java"
    pivot="java:org.apache.axis.transport.java.JavaSender"/>

<globalConfiguration>
<requestFlow>
  <handler type="java:com.ronghao.WSAxis.WSClientRequestHandler">
  <parameter name="keyStoreFile" value="D:/Tomcat5.5/webapps/axis/WEB-INF/client.keystore"/>
  <parameter name="keyEntryPassword" value="changeit"/>
  <parameter name="certAlias" value="serverkey"/>
  <parameter name="trustStorePassword" value="changeit"/>
  <parameter name="trustStoreFile" value="D:/Tomcat5.5/webapps/axis/WEB-INF/client.truststore"/>
  <parameter name="keyAlias" value="Client"/>
  <parameter name="keyStorePassword" value="changeit"/>
  </handler>
</requestFlow>
<responseFlow>
  <handler type="java:com.ronghao.WSAxis.WSClientResponseHandler">
  <parameter name="keyStoreFile" value="D:/Tomcat5.5/webapps/axis/WEB-INF/client.keystore"/>
  <parameter name="keyEntryPassword" value="changeit"/>
  <parameter name="certAlias" value="serverkey"/>
  <parameter name="trustStorePassword" value="changeit"/>
  <parameter name="trustStoreFile" value="D:/Tomcat5.5/webapps/axis/WEB-INF/client.truststore"/>
  <parameter name="keyAlias" value="Client"/>
  <parameter name="keyStorePassword" value="changeit"/>
  </handler>
</responseFlow>
</globalConfiguration>
</deployment>
同样不再解释,不明白可以参考我的上一篇文章

3、修改OrderClient.class
  在OrderClient.class中加入了如下 代码 :
  EngineConfiguration conf =
      new FileProvider("F://Tomcat//webapps//axis//WEB-INF//client-config.wsdd");//位置
  Service service = new Service(conf);
  当然记得导入
  import org.apache.axis.EngineConfiguration;
  import org.apache.axis.configuration.FileProvider;
  
运行一下,返回"ronghao",靠,搞定!
注意:这次我把OrderClient.class的调用放到了一个JSP文件中而不是jbuilder中,因为有client-config.wsdd,所以你必须有完整的WEB程序发布到TOMCAT中,否则会报找不到
相应文件。 

 
彻底理解numpy中的axis 时下流行人工智能,python成为人工智能最好的处理语言,这与python中的科学计算模块numpy是分不开的。numpy相信大都数人都知道。而在numpy中,有很多的函数都涉及到axis,numpy中的轴axis是很重要的,许多numpy的操作根据axis的取值不同,作出的操作也不相同。可以说,axis让numpy的多维数组变的更加灵活,但也让numpy变得越发难以理解。因此,弄清楚axis的... 阅读详情

相关推荐

axis=1什么时候对列,什么时候对行

这是因为这些计算是沿着行的方向“跨列”进行的,将每行中的元素作为一个集合来计算平均值、求和等。不过,在其他非聚合计算场景,比如数据拼接、对列元素应用复杂的自定义函数并返回多值结果(且以列作为操作单元)等情况下, axis = 1 也可以用于和列相关的操作,重点在于操作的逻辑单元是列方向的元素组合。二维数组有行和列两个维度,当计算平均值时, axis = 1 意味着“跨行”操作。在涉及计算平均值、求和等大多数常见的聚合计算时,在NumPy和pandas中, axis = 1 通常是对行进行操作。

a15997219373的博客 2645

Axis学习(一)

今天开始,我们来一起学习一下 Axis,我们以 Axis 1.4 版本为例。 一、准备环境:   1、Eclipse:http://www.eclipse.org/downloads/ 下载较新版本的 Eclipse,里面已经自带了WebService插件。   2、Axis1.4:下载 axis-bin-1_4.zip  文件。   3、JDK 1.6:这个就不用多说了。(1.6以前的版本也可以...

Salten(笑天) 362

axis、axis2客户端调用方式

最近做接口对接,对接的服务端是.net平台的webservices,用他们的wsdl文件不能生成axis2客户端,只能用axis调用,代码用的是天气预报的公网接口,都可正常使用 /** * axis直接调用 */ public static void getWeatherByAxis() { try { Service service = new Service(); ...

qq_34295193的博客 3507

cmd 生成wsdl文件_通过wsdl文件生成java客户端及简单调用

首先:下载安装axis1.4下载地址(http://download.youkuaiyun.com/download/u011255725/9911612)环境路径配置:classpath:D:\Axis2\axis1.4\axis-1_4\lib.在cc.bat中配置相关的生成规则(包括生成客户端的文件需要的关键jar包,生成文件目录和地址,wsdl文件等)如下:set AXIS_HOME=D:\Axis2...

weixin_39633976的博客 348

Eclipse中开发AXIS2 Web服务的完全解决方案

本文还有配套的精品资源,点击获取 简介:AXIS2是一个功能全面的开源Web服务框架,用于开发和部署SOAP和RESTful服务。"axis2-eclipse-service-plugin-1.6.2.zip"是AXIS2官方提供的Eclipse插件,它优化了在Eclipse中的Web服务开发流程。该插件支持从Java类自动生成WSDL文件,生成Java代码以构建客户端和W...

weixin_42186387的博客 1152

大模型-internvl高通qnn运行源码解读

模型链接:https://huggingface.co/OpenGVLab/InternVL2-2B论文官方简要说明 https://internvl.github.io/blog/2024-07-02-InternVL-2.0中文解读 https://zhuanlan.zhihu.com/p/702946079在线demo https://internvl.opengvlab.com/

点滴的岁月 1832

Axis的安装使用

1.可到http://download.youkuaiyun.com/detail/u013998070下载   将下载的文件解压,并将解压得到的axis-1.4/webapps/axis目录整体复制到Tomcat的webapps目录下,之后启动tomcat,  打开浏览器,输入:http://localhost:8080/axis/  如果你输入正确,将见到如下页页面: 点击validati

u013998070的专栏 1957

进程间通信的七种方法实战演示!值得收藏!

线程和进程间的通讯(Inter-Process Communication, IPC)是操作系统中的一个重要概念,用于实现不同进程或同一进程中的不同线程之间的数据交换和协调。以下是几个常见的进程间通信的方式:管道、消息队列、共享内存、信号、套接字、信号量、文件映射

十年饮冰,难凉热血,保持热爱,奔赴星海! 2816

AXIS的初级使用

1。从www.apache.org上下在axix的相关版本的包和sun公司的JAF的包(支持SOPA中的文件传输)。2。在适当的路径(即相关服务器的WEBAPPS目录下,因为AXIS本身可以看成一个WEB应用)下解压,把JAF中的activation.jar包放到其lib目录下。3。有关AXIS的环境的配置:AXIS_HOME: D:/Tomcat 5.0/webapps/axis/AXIS_

龙行天下 3092

高通410随身WiFi刷OpenWRT与Debian双系统一键集成方案

本文详细介绍高通410随身WiFi设备刷入OpenWRT与Debian双系统的一键集成方案。通过虎王工作室提供的一键刷机包,用户可轻松实现双系统部署,兼顾OpenWRT的网络功能与Debian的完整应用服务,适用于网络加速、服务器部署等多种场景,并提供了硬件资源分配与系统切换的实用指南。

docker7nomad的博客 1135

产业大脑+未来工厂:揭秘浙江数字经济系统的5大核心场景搭建指南

本文深入解析了“产业大脑+未来工厂”这一浙江数字经济系统的核心范式,并提供了五大核心场景的实战搭建指南。文章详细阐述了从供应链协同、产能共享到产品创新、质量追溯及绿色低碳等关键场景的构建逻辑与技术架构,旨在帮助企业实现从技术驱动到场景驱动的价值落地,破解数据孤岛难题,提升产业链整体效能。

mac99的博客 666

Tomcat5.0.28下AXIS完全安装手册

Tomcat5.0.28下AXIS完全安装手册2005-11-14 14:07 pm作者:ipaddr来自:linux宝库 (http://www.linuxmine.com)现存:http://www.linuxmine.com/3316.html联系:linuxmine#gmail.com不明白?欢迎到 linux论坛 (http://bbs.linuxmine.com) 参加讨论!网上有一些

pcfan1的专栏 3873

别再到处搜了!高德地图瓦片URL参数(lang、style、ltype)全解析与实战搭配指南

本文全面解析高德地图瓦片URL参数(lang、style、ltype)的核心逻辑与实战应用,提供18种实用参数组合方案,帮助开发者实现从基础到高阶的定制化地图渲染。涵盖语言控制、地图样式、图层类型等关键参数,并分享WebGIS项目中的优化技巧与常见问题解决方案。

weixin_33724046的博客 117

C++策略模式:从基础实现到高级应用

策略模式是面向对象编程中处理算法变体的经典设计模式,其核心思想是将算法封装为独立对象,使它们能够相互替换。这种模式通过接口与实现分离,提高了代码的扩展性和维护性。在C++中,策略模式可以基于虚函数实现传统面向对象版本,也能利用函数对象、模板等现代特性进行优化。该模式特别适用于算法需要动态切换的场景,如游戏AI行为控制、金融定价模型选择等高频变更需求。通过结合STL算法、lambda表达式等C++特性,策略模式能显著提升代码的灵活性和运行时性能。在实际工程中,合理运用策略模式可以有效解决类爆炸问题,同时保持系

weixin_33971977的博客 293

SAP SLT 在 carve-out 场景中的关键作用:从理论到实操全景展现

深入剖析 SAP Landscape Transformation(SLT Replication Server)在 carve‑out 场景中的价值,需要从 carve‑out 本身的背景逻辑说起。carve‑out 指的是企业因并购、拆分、剥离商业单元等因素,而将 SAP 系统中某部分业务(例如组织单元、公司代码、模块数据等) separated 出来,导入到独立的系统中。这一过程极具挑战性,既要确保业务连续性,又要实现数据精准迁移和系统隔离 (

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 7551

scratch绘制旋转彩球 2023年9月电子学会图形化编程scratch编程等级考试四级真题和答案解析

​ scratch绘制旋转彩球 2023年9月电子学会图形化编程Scratch等级考试四级真题 一、题目要求 1、准备工作 (1)删除小猫角色,从角色库选择Ball角色; (2)默认空白背景。 ​

青少年编程学习指导 1367

axis2 在myeclipse中生成webservice aar文件时 为嘛有时候点击next完全没反应啊,在线等。。。。

axis2 在myeclipse中生成webservice aar文件时 为嘛有时候点击next完全没反应啊,在线等。。。。

sangbody的专栏 1800

AI 实战篇 |基于 AI开放平台实现 人脸识别对比 功能,超详细教程【附带源码】

本篇文章来学习一下怎样使用 Unity实现简单地人脸识别 功能。 关于人脸识别,我们可以选择很多平台的SDK接入Unity来实现人脸识别的功能。

努力前行,总会成为自己心中的那道光 5万+

axis2 https is forbidden

对外提供的webservice接口,需要支持https方式访问, 不做任何修改会有https is forbidden的错误。 这时需要在web-inf下添加axis2.xml配置文件,该文件从官网可以下载。 该文件中有如下配置项,也即支持https的,需要监听的端口。                        class="org.apache.axis2.transport.h

业精于勤荒于嬉;行成于思,毁于随。 2552

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

Apache Axis

Apache Axis™ is a second generation SOAP engine, the successor to the Apache SOAP project, itself based on the original SOAP4J code that IBM contributed to Apache in April 2000. In contrast to its pr...

我的博客 526

SIMATIC S7-1200, S7-1500 PID 控制[手册]

SIMATIC S7-1200, S7-1500 PID 控制[手册]

区分使用Axis2和CXF的wsdl2java命令

在学习Web Service时,会接触到两个流行的Web Service框架CXF和Axis2,也需要对其进行环境变量的配置,配制方法如下: ·CXF环境变量配置: 1.在CLASSPATH中添加:D:\Libraries\apache-cxf-3.1.7\apache-cxf-3.1.7\lib 2.新建CXF_HOME D:\Libraries\apache-cxf-3.1.

JusterDu的博客 2432

霍尼韦尔SoftMaster使用说明

霍尼韦尔SoftMaster使用说明

Axis实践之Axis入门

第一部分: 安装Axis 第一步: 下载Axis 从Apache网站下载Axis发布包: http://ws.apache.org/axis/ 我下载的是 Axis 1.4 Final 版 第二步: 解压Axis压缩包 把下载的axis-bin-1_4.zip包解压缩到一个文件夹,可以是任意的,但如果文件夹包含中文名时,在中间有些过程需要对中文进行一些处理,否则可能出错; 我把axis-bin-1

阳光下的立人 999

Python数据分析中 DataFrame axis=0与axis=1的理解

python中的axis究竟是如何定义的呢?他们究竟代表是DataFrame的行还是列? 直接上代码 people=DataFrame(np.random.randn(5,5), columns=['a','b','c','d','e'], index=['Joe','Steve','Wes','Jim','Travis']) #...

m0_37468171的博客 6429
上一篇: a bit of java (from forum)
下一篇: WebService 的发布
baobeiSimple
博客等级 码龄20年 61粉丝 49原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值