Soap协议扩展的应用及实现

原创 2004年10月18日 17:33:00

Soap协议扩展的应用及实现




Soap协议 (简单对象传输)是一种基于 XML 的、用于在 Web 上交换结构化和类型信息的简单的轻量协议。SOAP 的总体设计目标是使其尽可能地简单,并提供最少的功能。该协议定义一个不包含任何应用程序或传输语义的消息处理框架。因此,该协议是模块化的,并具有很强的扩展性。
Soap 协议规范包含四个主要组成部分。第一部分定义用于封装数据的必需的可扩展信封。该 SOAP 信封定义 SOAP 消息,并且是 SOAP 消息处理器之间的基本交换单位。这是该规范唯一必需的部分。
SOAP 协议规范的第二部分定义用来表示应用程序定义的数据类型和有向图形的可选数据编码规则,以及用于序列化非句法数据模型的统一模型。
第三部分定义 RPC 样式(请求/响应)的消息交换模式。每个 SOAP 消息都是单向传输。尽管 SOAP 的根位于 RPC 中,但它不仅仅只是请求/响应机制。XML Web services 经常组合 SOAP 消息以实现此类模式,但 SOAP 并不强制要求消息交换模式,这部分规范也是可选的。
规范的第四部分定义 SOAP 和 HTTP 之间的绑定。但该部分也是可选的。可以将 SOAP 与任何能够传输 SOAP 信封的传输协议或机制(包括 SMTP FTP 甚至软盘)结合在一起使用。
Microsoft公司实现了soap协议,并使之成为.Net Framework的一个重要的基础.Microsoft.net的任何基于client-server的传输都是以soap的形式的.(httpGet 及httpPost 协议只是client应用).
举一个.Net的例子.如一个web service程序是 data.asmx:
<%@ WebService Language="C#" Class="data" %>
using System;
using System.Web.Services;
public class Order
{
public int OrderID;
public double Price;
}
public class data {
[WebMethod]
public Order GetOrder()
{
Order myOrder = new Order();
myOrder.Price=34.5;
myOrder.OrderID = 323232;
return myOrder;
}
}
现再用wsdl工具将web serivce的wsdl转换成client的代理程序,如:wsdl /protocol:Soap /namespace:D http://localhost/data1.asmx
(假设data1.asmx是放在iis服务器的根目录下(c:/inetpub/wwwroot)).
产生一个客户端的代理程序data.cs:
namespace D {
using System.Diagnostics;
using System.Xml.Serialization;
using System;
using System.Web.Services.Protocols;
using System.ComponentModel;
using System.Web.Services;
/// <remarks/>
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Web.Services.WebServiceBindingAttribute(Name="dataSoap", Namespace="http://tempuri.org/")]
public class data : System.Web.Services.Protocols.SoapHttpClientProtocol {
/// <remarks/>
public data() {
this.Url = "http://localhost/data1.asmx";
}
/// <remarks/>
[System.Web.Services.Protocols.SoapDocumentMethodAttribute("http://tempuri.org/GetOrder", RequestNamespace="http://tempuri.org/", ResponseNamespace="http://tempuri.org/", Use=System.Web.Services.Description.SoapBindingUse.Literal, ParameterStyle=System.Web.Services.Protocols.SoapParameterStyle.Wrapped)]
public Order GetOrder() {
object[] results = this.Invoke("GetOrder", new object[0]);
return ((Order)(results[0]));
}
/// <remarks/>
public System.IAsyncResult BeginGetOrder(System.AsyncCallback callback, object asyncState) {
return this.BeginInvoke("GetOrder", new object[0], callback, asyncState);
}
/// <remarks/>
public Order EndGetOrder(System.IAsyncResult asyncResult) {
object[] results = this.EndInvoke(asyncResult);
return ((Order)(results[0]));
}
}
/// <remarks/>
[System.Xml.Serialization.XmlTypeAttribute(Namespace="http://tempuri.org/")]
public class Order {
/// <remarks/>
public int OrderID;
/// <remarks/>
public System.Double Price;
}
}
然后再将之编译成dll.如:csc /t:library /out:c:/inetpub/wwwroot/bin/data.dll data.cs.完成以后就可以使用.Net的client程序进行调用(如winform ,cs or aspx).
下面是用test.aspx实现client的调用的.
<%@ Import Namespace="D" %>
<html>
<style>
div
{
font: 8pt verdana;
background-color:cccccc;
border-color:black;
border-width:1;
border-style:solid;
padding:10,10,10,10;
}
</style>
<script language="C#" runat="server">
public void Page_Load(Object sender, EventArgs E)
{
data datatype =new data();
Order or=datatype.GetOrder();
Response.Write("order -==="+or.OrderID+"<br>");
}
</script>
</body>
</html>
运行这个程序,将在浏览器打印"order=======323232".
我们来研究client 同server到底传输了什么.
当我们执行test.aspx时,它调用到了data.cs的GetOrder()方法,然后序列化信息,并包装成:
<?xml version="1.0" encoding="utf-8"?><soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"><soap:Body><GetOrder xmlns="http://tempuri.org/" /></soap:Body></soap:Envelope>
传输到server上,server接受信息以后,反序列化,然后调用server上的GetOrder()方法,得到一个返回值并序列化,得到一个流:
<?xml version="1.0" encoding="utf-8"?><soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"xmlns:xsi=
"http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"><soap:Body><GetOrderResponse xmlns ="http://tempuri.org/"><GetOrderResult><OrderID>323232</OrderID><Price>34.5
</Price></GetOrderResult></GetOrderResponse></soap:Body></soap:Envelope>传输到client端.client端收到信息后再反序列得到值.
从上分析可知,soap协议就是一个传输数据的作用.但网络的传输是复杂的且有许多的不定因素,怎样去考虑安全性呢?client怎样确定server发的是可靠的信息而server又怎样辨认client呢?
Microsoft推出了Soap extension(扩展),来实现soap消息的加密与解密.
从下图可以看出soap扩展的用途:

02_4_22.gif

正如您看到的,ASP.NET 在 XML Web services 计算机和 XML Web services 客户端计算机上的阶段中对 XML 进行序列化和反序列化。可以将 SOAP 扩展插入基础结构以在每个序列化和反序列化阶段的之前和之后检查或修改 SOAP 消息。例如,加密 SOAP 扩展可能在 ASP.NET 序列化客户端的参数之后加密 SOAP 消息的 XML 部分,而后在 ASP.NET 反序列化 SOAP 消息之前在 Web 服务器上解密 SOAP 消息。这些阶段(SOAP 扩展可能在这些阶段中检查或修改 SOAP 消息)是在 SoapMessageStage 枚举中定义的。在这种情况下,在 AfterSerialize 阶段加密 SOAP 扩展,在 BeforeDeserialize 阶段解密 SOAP 扩展。
通常,当 SOAP 扩展修改 SOAP 消息的内容时,必须在客户端和服务器上都进行修改。也就是说,如果要在客户端上运行 SOAP 扩展并加密 SOAP 消息,则相应的 SOAP 扩展必须在服务器上对该 SOAP 消息进行解密。如果未解密该 SOAP 消息,则 ASP.NET 基础结构不能将 SOAP 消息反序列化为对象。当然,不修改 SOAP 消息的 SOAP 扩展(例如仅记录 SOAP 消息的 SOAP 扩展)可以只在客户端或服务器上运行。在这种情况下,接收方接收与在 SOAP 扩展不运行并且 ASP.NET 基础结构可以反序列化 SOAP 消息的情况下相同的 SOAP 消息。另外,如果 SOAP 扩展不以一种使反序列化不能实现的方式对 SOAP 进行修改,则 SOAP 扩展不需要既运行在客户端又运行在服务器上。
调用 SOAP 扩展方法的顺序
我们看看在整个 XML Web services 方法调用过程中 ASP.NET 何时调用 SOAP 扩展方法。下面的步骤假设 SOAP 扩展既运行于客户端又运行于服务器上。如果 SOAP 扩展不同时运行于客户端和服务器上,则 ASP.NET 将忽略与 SOAP 扩展运行于其中任何一个相关联的步骤。
客户端
1. 客户端对代理类调用方法。
2. 在客户端上创建 SOAP 扩展的新实例。
3. 如果这是第一次在客户端上用该 XML Web services 执行该 SOAP 扩展,则对运行于客户端上的 SOAP 扩展调用 GetInitializer 方法。
4. 调用 Initialize 方法。
5. 调用 ChainStream 方法。
6. 调用 ProcessMessage 方法,调用时将 SoapMessageStage 设置为 BeforeSerialize。
7. 客户端计算机上的 ASP.NET 将 XML Web services 方法的参数序列化为 XML。
8. 调用 ProcessMessage 方法,调用时将 SoapMessageStage 设置为 AfterSerialize。
9. 客户端计算机上的 ASP.NET 通过网络将 SOAP 消息发送到承载该 XML Web services 的 Web 服务器。
服务器端
1. Web 服务器上的 ASP.NET 接收该 SOAP 消息。
2. 在 Web 服务器上创建 SOAP 扩展的新实例。
3. 在 Web 服务器上,如果这是第一次在服务器端使用该 XML Web services 执行该 SOAP 扩展,则对运行于服务器上的 SOAP 扩展调用 GetInitializer 方法。
4. 调用 Initialize 方法。
5. 调用 ChainStream 方法。
6. 调用 ProcessMessage 方法,调用时将 SoapMessageStage 设置为 BeforeDeserialize。
7. ASP.NET 反序列化 XML 中的参数。
8. 调用 ProcessMessage 方法,调用时将 SoapMessageStage 设置为 AfterDeserialize。
9. ASP.NET 创建实现 XML Web services 的类的新实例并调用 XML Web services 方法,同时传入反序列化的参数。该对象驻留在与 Web 服务器相同的计算机上。
10. XML Web services 方法执行其代码,最终会设置返回值和任何输出参数。
11. 调用 ProcessMessage 方法,调用时将 SoapMessageStage 设置为 BeforeSerialize。
12. Web 服务器上的 ASP.NET 将返回值和输出参数序列化为 XML。
13. 调用 ProcessMessage 方法,调用时将 SoapMessageStage 设置为 AfterSerialize。
14. ASP.NET 通过网络将 SOAP 响应消息发送回 XML Web services 客户端。
客户端
1. 客户端计算机上的 ASP.NET 接收 SOAP 消息。
2. 调用 ProcessMessage 方法,调用时将 SoapMessageStage 设置为 BeforeDeserialize。
3. ASP.NET 将 XML 反序列化为返回值和任何输出参数。
4. 调用 ProcessMessage 方法,调用时将 SoapMessageStage 设置为 AfterDeserialize。
5. ASP.NET 将返回值和任何输出参数传递到代理类的实例。
6. 客户端接收返回值和任何输出参数。
我们现在以.Net的一个例子说明soap扩展的应用.
首先,我们写一个soap extension的程序,它是继承SoapExtension而来.
( TraceExtension.cs)
using System;
using System.Web.Services;
using System.Web.Services.Protocols;
using System.IO;
using System.Net;
// Define a SOAP Extension that traces the SOAP request and SOAP
// response for the XML Web service method the SOAP extension is
// applied to.
public class TraceExtension : SoapExtension
{
Stream oldStream;
Stream newStream;
string filename;
// Save the Stream representing the SOAP request or SOAP response into
// a local memory buffer.
public override Stream ChainStream( Stream stream ){
oldStream = stream;
newStream = new MemoryStream();
return newStream;
}
// When the SOAP extension is accessed for the first time, the XML Web
// service method it is applied to is accessed to store the file
// name passed in, using the corresponding SoapExtensionAttribute.
public override object GetInitializer(LogicalMethodInfo methodInfo, SoapExtensionAttribute attribute)
{
Stream fs = new FileStream("d://temp//a.txt", FileMode.Create);
StreamWriter writer=new StreamWriter(fs);
writer.WriteLine("extension is ok ");
//writer.Flush();
//fs.Close();
writer.Close();
return ((TraceExtensionAttribute) attribute).Filename;
}
// The SOAP extension was configured to run using a configuration file
// instead of an attribute applied to a specific XML Web service
// method.
public override object GetInitializer(Type WebServiceType)
{
// Return a file name to log the trace information to, based on the
// type.
return WebServiceType.GetType().ToString() + ".log";
}
// Receive the file name stored by GetInitializer and store it in a
// member variable for this specific instance.
public override void Initialize(object initializer)
{
Stream fs = new FileStream("d://temp//b.txt", FileMode.Create);
StreamWriter writer=new StreamWriter(fs);
writer.WriteLine("extension bb is ok ");
//writer.Flush();
//fs.Close();
filename = (string) initializer; //监控文件是:c:/winnt/system32/system.runtimetype.log
writer.WriteLine("filename ========="+filename);
writer.Close();
}
// If the SoapMessageStage is such that the SoapRequest or
// SoapResponse is still in the SOAP format to be sent or received,
// save it out to a file.
public override void ProcessMessage(SoapMessage message) //处理传输的数据.
{
switch (message.Stage) {
case SoapMessageStage.BeforeSerialize:
break;
case SoapMessageStage.AfterSerialize:
WriteOutput(message);
break;
case SoapMessageStage.BeforeDeserialize:
WriteInput(message);
break;
case SoapMessageStage.AfterDeserialize:
break;
default:
throw new Exception("invalid stage");
}
}
public void WriteOutput(SoapMessage message){// 可以添加解密算法
newStream.Position = 0;
FileStream fs = new FileStream(filename, FileMode.Append,
FileAccess.Write);
StreamWriter w = new StreamWriter(fs);
string soapString = (message is SoapServerMessage) ? "SoapResponse" : "SoapRequest";
w.WriteLine("-----out ----" + soapString + " at " + DateTime.Now);
w.WriteLine("message ====="+message.MethodInfo.Name);
w.Flush();
Copy(newStream, fs);
w.Close();
newStream.Position = 0;
Copy(newStream, oldStream);
}
public void WriteInput(SoapMessage message){//可以添加加密算法
Copy(oldStream, newStream);
FileStream fs = new FileStream(filename, FileMode.Append,
FileAccess.Write);
StreamWriter w = new StreamWriter(fs);
string soapString = (message is SoapServerMessage) ?
"SoapRequest" : "SoapResponse";
w.WriteLine("-----int -------" + soapString +
" at " + DateTime.Now);
w.Flush();
newStream.Position = 0;
Copy(newStream, fs);
w.Close();
newStream.Position = 0;
}
void Copy(Stream from, Stream to)
{
TextReader reader = new StreamReader(from);
TextWriter writer = new StreamWriter(to);
writer.WriteLine(reader.ReadToEnd());
writer.Flush();
}
}
// Create a SoapExtensionAttribute for the SOAP Extension that can be
// applied to an XML Web service method.
[AttributeUsage(AttributeTargets.Method)]
public class TraceExtensionAttribute : SoapExtensionAttribute {
private string filename = "c://log.txt";
private int priority;
public override Type ExtensionType {
get { return typeof(TraceExtension); }
}
public override int Priority {
get { return priority; }
set { priority = value; }
}
public string Filename {
get {
return filename;
}
set {
filename = value;
}
}
}
我们将它编译成dll文件,如:csc /t:library /out:c:/inetpub/wwwroot/bin/TraceExtension.dll TraceExtension.cs
然后我们再写一个配置文件: web.config:
<configuration>
<system.web>
<webServices>
<soapExtensionTypes>
<add type="TraceExtension,TraceExtension" priority="1" group="0" />
</soapExtensionTypes>
</webServices>
</system.web>
</configuration>
将web.config存入c:/inetpub/wwwroot目录.
最后我们再运行test.aspx,我们可以在c:/winnt/system32/system.runtimetype.log文件中找到client与server端所传输的数据.我们可以在TraceExtension.cs 中的ProcessMessage(SoapMessage)方法中加上加密及解密算法,改变client-server传输的数据.
总之,soap扩展在安全保密方面是非常有用的.

c# Web Services学习笔记(一、SOAP协议概述)

一、SOAP协议概述    soap简单对象访问协议,是一个用来在分散/分布式的环境中交换信息的简单协议,是一个基于xml的协议。soap本身是一个无状态的、单向的消息交换机制。    soap中没有...
  • changyuming
  • changyuming
  • 2008年10月09日 11:04
  • 2786

SOAP协议和基于SOAP的开发流程详述

简单对象访问协议(SOAP)是交换数据的一种协议规范,是一种轻量的、简单的、基于XML的协议,它被设计成在WEB上交换结构化的和固化的信息。 在实际的软件开发项目中,SOAP大多用于处理用户数据,也即...
  • zhouzxi
  • zhouzxi
  • 2015年09月10日 18:45
  • 10249

SOAP概述和结构

在介绍WSDL时,指出web服务传送消息的协议是SOAP,那soap是什么呢?SOAP(Simple Object Access Protocol),简单对象访问协议,作用就是规定发送消息的格式和使用...
  • whuqin
  • whuqin
  • 2011年04月16日 21:27
  • 2783

Java实现SOAP协议

Java实现SOAP协议   SOAP是把基于HTTP的WEB技术与XML的灵活性和可扩展性组合在了一起。 准备: 1. 准备一个web server。Tomcat 下...
  • bestlove12345
  • bestlove12345
  • 2016年07月07日 11:10
  • 1770

PHP SOAP 扩展详解

PHP SOAP 扩展SOAP 的全称为简单对象访问协议 (Simple Object Access Protocol)。它是一种基于 XML 的,可扩展的通信协议。SOAP 提供了一种标准,使得运行...
  • lfq618
  • lfq618
  • 2010年04月22日 10:19
  • 8897

【soap】SOAP扩展PHP轻松实现WebService

最近在一个PHP项目中对接外部接口涉及到WebService,搜索引擎上相关文章不是很多,找到的大都是引用一个号称很强大的开源软件NuSOAP(下载地址:http://sourceforge.net/...
  • yanhui_wei
  • yanhui_wei
  • 2014年03月28日 18:20
  • 2560

PHP中安装soap模块 扩展 方法

PHP中安装soap模块方法 一、Linux下安装soap模块 安装完php后最好保留当时安装的文件,比如usr/local/php-5.3.2 查看soap模块是否安装的办法:在php的安装目录下运...
  • terry_water
  • terry_water
  • 2015年06月30日 09:55
  • 5146

vc soap例子

#include #import "msxml3.dll" using namespace MSXML2; #import "C:\P...
  • cupidove
  • cupidove
  • 2014年03月16日 12:01
  • 1814

webservice--CXF发布SOAP协议的服务

CXF发布SOAP协议的服务 一、需求 服务端:发布服务,接收客户端的城市名,返回天气数据给客户端 客户端:发送城市名给服务端,接收服务端的响应信息,打印 二、实现 1、服务端 开发步骤: ...
  • CSDN_GIA
  • CSDN_GIA
  • 2017年02月05日 15:54
  • 518

Jmeter实现webservice协议的脚本

1. 打开Jmeter,新建线程组,并添加一个SOAP/XML-RPC Request取样器。 2. 在URL输入栏输入地址:http://www.webxml.com.cn/WebServices...
  • luotuofeile
  • luotuofeile
  • 2015年09月12日 23:00
  • 839
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Soap协议扩展的应用及实现
举报原因:
原因补充:

(最多只允许输入30个字)