第二部分 对SOAP消息头的处理
SOAP消息头通常包含与消息体或SOAP处理(应用)方式相关的信息,比如消息路径、数字签名、认证信息,消息关联性信息、消息体的加密公匙等等。同第一部分一样我们可以利用属性机制来获取控制SOAP消息头的句柄,对SOAP消息头进行自定义,然后将头数据传递到Web services 方法或从Web services方法返回头数据。消息头数据是不直接与Web services 方法的主功能相关的,因为它不是Web services方法的参数。
1.服务提供端的工作
我将以一个简单的认证服务作为例子,来讲解如何在程序中定义和使用自定义的消息头。首先我们所需要做的事情,就是在Web Service端从抽象类SoapHeader继承一个类(假设类名为AuthenticationHeader),用来表示SOAP消息头内的数据,注意这个类的类名将是SOAP消息头下的根元素(SOAP消息头的子元素)的名字(<soap:Header><AuthenticationHeader>…</AuthenticationHeader></soap:Header>),而类的公共成员变量名或属性名(假设一个属性名为AuthenticationToken)将是其下的子元素的名字(<soap:Header><AuthenticationHeader><AuthenticationToken>。。。</AuthenticationToken></AuthenticationHeader></soap:Header>)。对于客户端所发送的请求消息的消息头就需要遵守这个格式,向Web Service方法提供需要的信息。当Web Service方法接收到SOAP消息后,会进行并行化操作,根据定义新建一个SOAP头类对象,然后将SOAP消息头内的数据赋给该对象的相应属性,以便Web Service方法直接利用。以下就是该认证消息头类的主要代码:
public class AuthenticationHeader : SoapHeader
{
private string _AuthenticationToken = String.Empty;
//该属性允许Web Service设置和获取SOAP Header的AuthenticationToken元素的值
public string AuthenticationToken
{
get { return _AuthenticationToken; }
set { //验证接收到的AuthenticationToken元素的值,如果为空则抛出异常
if (value == String.Empty)
{
throw new SoapException("No Authentication Token Received",null);
}
_AuthenticationToken = value;
}
}
}
一旦定义好了消息头的格式,下一步的工作就是将SOAP消息头的数据与Web method关联起来。SoapHeader属性就是用来做这项工作的。首先需要向提供服务的WebService类添加一个公共成员变量(本例中为AuthHeader),这个变量的类型就是上面从SoapHeader类继承的那个类AuthenticationHeader。这里又引入了一个属性SoapHeader,这个SoapHeader实际上就是SoapHeaderAttribute,SoapHeaderAttribute类的构造函数将头类变量的名字作为参数,并且加在了一个WebMethod的前面,这是为了将该SOAP头类与指定的Web Service方法关联起来,作为该WebMethod的一部分。下面是服务端WebService类的主要代码:
public class SoapHeaderDemo : System.Web.Services.WebService
{
public AuthenticationHeader AuthHeader;
// public ReceiptorHeader ReceiptHeader = new ReceiptorHeader();
…
//SOAP header将确保每个用户都与一个Authenticationtoken相关联
[WebMethod]
[SoapHeader("AuthHeader", Direction=SoapHeaderDirection.In, Required=true)]
// [SoapHeader("ReceiptHeader", Direction=SoapHeaderDirection.Out, Required=true)]
public Account GetAccountDetails(int accountID)
{
//将认证标记传到Account的构造函数中,以便查询该标记对应的UserID。由于前面引入了// SoapHeader属性,这里就可以直接使用头类对象了
Account ad = new Account(accountID,AuthHeader.AuthenticationToken);
//如果UserID和AccountID都匹配,则说明认证成功,返回一个Account对象
return ad;
}
}
请注意,这里没有创建SOAP头类对象AuthHeader的实例,因为AuthHeader处理的是来自客户端的SOAP消息头。由于SoapHeader属性的属性项Direction = SoapHeaderDirection.In,ASP.NET运行时会在接收到来自客户端的消息后自动创建AuthHeader的实例,并用SOAP消息头内的数据对其相应属性赋值。如果WebService方法要向客户端发送SOAP消息头(假设根元素为ReceiptorHeader),则必须对该头类对象(假设SOAP头类对象为ReceiptHeader)实例化,且服务端对应的SoapHeader属性的属性项Direction=SoapHeaderDirection.Out
SOAP属性里有两个属性项Direction和Required。Direction说明SOAP消息是从客户端发送到服务端(In)还是刚好相反(Out),或是两者都有(InOut)。 Required则指明消息头是否必须被包括在SOAP消息中。如果指定为True而没有包括,ASP.NET会抛出异常(SoapException,后面会讲到)。Required默认值为True,此时ASP.NET不支持HTTP GET/POST 绑定,也就是说不能通过ASP.NET自动生成的测试页来访问这个Web Method了。注意,“必须包含”并不表示“必须处理”,事实上完全有可能你向服务端发送了要求包含的SOAP消息头数据,而Web Service却并没有做任何处理(你会不会感觉有点“浪费表情”^_^),但这不会抛出任何异常。
另外,Required与Web service接口紧密相关,对这个属性的改变会影响到该Web service的WSDL。如果Required设置为True,则在SOAP 绑定扩展性元素中定义的header元素的required属性也被设为true,同时在WSDL里会出现对消息头元素的Schema定义,客户端的SOAP消息头格式必须符合这个定义,否则服务端会抛出异常。
现在客户端传过来的SOAP消息头内的数据与Web Method已经关联起来了,并可直接通过头类对象访问,其余的工作就是完善验证和数据处理功能的代码,这里就不再熬述了。
2.客户端的工作
上面提到的是服务端的处理,那客户端如何在调用Web Method时将消息头加进去呢?方法就是通过客户端代理类创建WebService端消息头类(本例为AuthenticationHeader)对象的实例,将需要发送的数据赋到相应的公共成员变量里去,再调用Web Method就行了。下面给出一个在请求消息中添加信息头的例子:
//从本地取得用户的认证标记
_authToken = (string)this.ViewState["AuthToken"];
//生成代理类对象
SoapHeaderClient.localhost.SoapHeaderDemo demo =
new SoapHeaderClient.localhost.SoapHeaderDemo();
//生成代理头类对象
demo.AuthenticationHeaderValue =
new SoapHeaderClient.localhost.AuthenticationHeader();
//将认证标记添加到代理头类对象的相应元素中
demo.AuthenticationHeaderValue.AuthenticationToken = _authToken;
3.SOAP Header的属性
但是这里还有个问题,客户端向服务端发送的SOAP消息头除了Web Method能够处理的以外,可能还包括了一些Web Method不能识别(更不能处理)的SOAP消息头。更可怕的是客户端甚至可能将这些服务端不能识别的SOAP消息头所对应的SOAP头类对象的MustUnderstand属性设置为true,这样可就麻烦了。呵呵,幸运的是.NET还提供了一种机制专门解决这种不明SOAP消息头的处理问题。首先我们还是来了解一下MustUnderstand属性吧。
MustUnderstand属性来自于SoapHeader类,它与前面讲到的SoapHeaderAttribute类的Required属性完全不同,它表示消息的接收者是否必须理解(处理)这个指定的消息头。
DidUnderstand也是SoapHeader类的一个属性,在Web method中可以通过设置某个头类对象的DidUnderstand属性的值,来告诉客户端哪些信息头已经被处理,哪些没有处理。对于由Web method定义的消息头,DidUnderstand的默认值为true。需要指出的是,对于客户端mustUnderstand属性设置为True而在Web method中却没有处理的消息头,要么将DidUnderstand属性的值设为False,要么就主动抛出一个异常,否则就会出错!在Web Method返回前,.NET会检查所有客户端传过来的SoapHeader,一旦发现客户端将mustUnderstand属性设置为True,而对应的DidUnderstand属性却为False,就会抛出SoapHeaderException异常。
针对上面SOAP消息头可能没有处理的情况,可以在Web method的开始部分将所有SoapHeader的DidUnderstand属性设置为False,一旦某个SoapHeader被处理了,就将其DidUnderstand设置为True。或者在Web method决定是否对某个SoapHeader进行处理时,将客户端设置的MustUnderstand属性的值作为一个判断条件。
4.不明SOAP消息头的处理
.NET提供了一种机制来处理没有被Web method正式定义的Soap Header(SoapUnknownHeader)。SoapUnknownHeader类继承自SoapHeader,因此也有 MustUnderstand和DidUnderstand属性。SoapUnknownHeader类型的对象是松散的,它自己定义的属性只有Element(XmlElement类型),Element属性用来访问不明Soap头类的根元素,可以通过它来遍历该头类的所有元素的内容。
和其它SoapHeader类一样,可以通过SoapHeader属性将SoapUnknownHeader与Web method关联起来。如果有不只一个SoapUnknownHeader,SoapHeader属性的MemberName属性项就是一个数组。下面是一个处理不明SOAP消息头例子:
public class MyWebService
{
public MyHeader myHeader;
// 声明数组准备接收所有的不明SOAP消息头
public SoapUnknownHeader[] unknownHeaders;
[WebMethod]
[SoapHeader ("myHeader", Direction=SoapHeaderDirection.InOut,Required=true)]
//通过SoapHeader属性,接受所有不明SOAP消息头
[SoapHeader ("unknownHeaders", Required=false)]
public string MyWebMethod()
{
string unknownHeaderAttributes = String.Empty;
// 处理已知消息头myHeader,过程略
// 检查每个不明SOAP消息头
foreach (SoapUnknownHeader header in unknownHeaders)
{
// 列出每个不明SOAP消息头的根元素的每个属性名值对
foreach (XmlAttribute attribute in header.Element.Attributes)
{
unknownHeaderAttributes = unknownHeaderAttributes + attribute.Name + ":" + attribute.Value + ";";
}
// 告诉客户端,这些不明SOAP消息头不能够处理
header.DidUnderstand = false;
}
return unknownHeaderAttributes;
}
}
对于这个例子,如果客户端要求必须对某个不明SOAP消息头进行处理,在Web Method返回时会自动抛出异常(或主动抛出异常,详细描述),客户端可以根据异常原因来决定进一步的操作。
5.SOAP异常
当客户端使用SOAP进行调用时,由于各种各样的原因Web Services方法可能会引发SoapException(继承自Exception类),比如名称空间不匹配、SOAP头未处理(此时引发SoapHeaderException)、编码格式不被识别、数据库处理错误、主动抛出异常等等。异常在服务器上被捕获并包装在一个新的SoapException实例内,然后写入SOAP体(Body)的Fault元素中,作为响应返回给客户端。下面是一个返回异常的SOAP消息体:
<soap:Body>
<soap:Fault>
<faultcode>soap:Server</faultcode> --错误码
<faultstring>System.Web.Services.Protocols.SoapHeaderException: 服务器在消息中未找到所需的 AuthenticationHeader SOAP 标头。
at System.Web.Services.Protocols.SoapHeaderHandling.SetHeaderMembers(SoapHeaderCollection headers, Object target, SoapHeaderMapping[] mappings, SoapHeaderDirection direction, Boolean client)
at System.Web.Services.Protocols.SoapServerProtocol.CreateServerInstance()
at System.Web.Services.Protocols.WebServiceHandler.Invoke()
at System.Web.Services.Protocols.WebServiceHandler.CoreProcessRequest()
</faultstring> --错误内容
<detail /> --在抛出异常时自定义的详细错误信息,这里为空
</soap:Fault>
</soap:Body>
前面说过.NET会自动根据错误原因和类型生成相应的异常,同时Web Services也可以根据需要人工抛出异常,不管是SoapException,还是普通的Exception,例如:
SoapException se = new SoapException("Fault occurred", SoapException.ClientFaultCode,Context.Request.Url.AbsoluteUri,node);
throw se;
或
throw new Exception("Fault occurred");
而客户端可以通过下面的方法来获取关于异常的详细信息:
try
{ … }
catch (Exception e)
{
Console.WriteLine(e.Source);
Console.WriteLine(e.Message);
//SoapException的属性
Console.WriteLine(e.Code);
Console.WriteLine(e.Actor);
Console.WriteLine(e.Detail);
}
http://clockzxj.blog.163.com/blog/static/18950624200711441727132/
分享到:
相关推荐
在Java中,你可以使用JAX-WS(Java API for XML Web Services)来处理SOAP消息头。以下是一个简单的示例: 1. **创建消息监听器**: ```java import javax.xml.ws.handler.MessageContext; import javax.xml.ws....
SOAP SDK是软件开发工具包,专为微软平台设计,用于简化和处理SOAP消息的创建、发送和解析。它提供了丰富的功能,使得开发者能够在应用程序中集成SOAP服务,实现不同系统间的互操作性。 在SOAP消息处理中,SDK扮演...
在某些场景下,开发者可能只需要关注SOAP消息头中的信息,而无需处理消息体。例如,在进行安全性验证、路由选择或者添加日志记录时,只需关注消息头即可。这种情况下,仅解析SOAP消息头而不解析消息体可以提高性能,...
SOAP消息解析是理解、处理和构建SOAP请求和响应的关键步骤。在这个"soap消息解析.rar"压缩包中,包含的是易语言编写的SOAP消息解析源码,这是一种面向过程的编程语言,常用于开发Windows应用程序。 SOAP消息由四个...
SOAP(Simple Object Access ...在实际的文章中,作者可能深入讨论了更复杂的话题,如SOAP消息的安全性、错误处理、WS-*扩展(如WS-Security、WS-Addressing等),或者是如何在特定的开发环境中集成和使用SOAP服务。
在Java中,我们通常使用JAX-WS(Java API for XML Web Services)来创建和处理SOAP消息。JAX-WS允许你通过注解来定义服务接口和服务实现,以及客户端调用这些服务的方式。以下是一些关键的Java类和接口,用于操作...
SOAP头是SOAP消息的一个可选部分,它包含了除消息体之外的附加信息,如安全凭证、交易ID或者路由信息。在CXF中,我们可以利用Interceptors(拦截器)机制来处理这些头部信息。 1. **创建SOAP头对象** 在CXF中,你...
- **SOAP Header**:可选元素,用于存储消息头信息,如认证信息等。 - **SOAP Body**:必需元素,包含所有的请求和响应信息。 - **SOAP Fault**:可选元素,当出现错误时提供相关信息。 #### 三、SOAP消息基本结构 ...
2. **序列号机制**:为每个SOAP消息分配唯一的序列号,服务提供者记录已接收的消息序列号,拒绝处理重复的序列号。 3. **挑战-响应机制**:这是一种简化的方法,服务提供者向请求者发送随机字符串(挑战),请求者...
### SOAP入门:深入理解与应用 #### 一、SOAP基础知识概览 SOAP(Simple Object Access Protocol)是一种...通过以上内容的学习,读者应能掌握SOAP消息的基本构建和处理方法,为后续的Web服务开发打下坚实的基础。
SOAP消息处理过程涉及到消息的创建、传递和接收,以及在消息发送和接收端对消息进行序列化(编码)和反序列化(解码)的操作。具体过程包括: 1. 客户端SOAP代理模块将RPC调用编码成SOAP请求消息,此过程中,客户端...
当我们谈论“PHP SOAP头验证”时,我们指的是在使用PHP作为客户端或者服务器端来处理SOAP请求时,如何验证消息头中的信息,确保数据的安全性和准确性。 在服务器端,SOAP头验证是验证接收到的SOAP请求中的头部信息...
SOAP消息通常包含三个主要部分:Header、Body和Envelope。 1. **SOAP Envelope**:这是SOAP消息的核心,定义了消息的基本结构。它告知接收者这是一条SOAP消息,并包含了消息的其他组成部分。XML标签`<soap:Envelope...
SOAP封装(SOAP Envelop)是SOAP消息的核心,它定义了一个框架,描述了消息的内容、发送者、接收者以及如何处理这些内容。它包含三个主要元素:Envelope、Header和Body。Envelope是SOAP消息的根元素,用于标识XML...
在实际应用中,SOAP消息的创建和解析涉及XML解析、命名空间处理、错误处理等多个方面。为了确保兼容性和正确性,SOAP应用程序必须能够识别和处理正确的命名空间,并且忽略或处理不包含SOAP命名空间的消息。 总结...
在SOAP消息处理中,Handler扮演着至关重要的角色。它允许开发者插入自定义逻辑到SOAP消息的生命周期中,从而在消息被发送前或接收后进行拦截和修改。SOAP Handler是SOAP绑定层的一部分,它们遵循SOAP Handler链模型...
2. **SOAP命名空间管理**:理解如何在SOAP消息中正确处理命名空间,因为XML元素可能属于不同的命名空间,这在解析和生成XML时是非常关键的。 3. **错误处理**:观察QtSoap是如何处理解析错误、网络错误和其他可能...
SOAP消息由以下几个XML元素构成: 1. 必须的Envelope元素,用于标识XML文档为SOAP消息。 2. 可选的Header元素,包含头部信息,如身份验证、路由等。 3. 必须的Body元素,包含了所有调用和响应信息。 4. 可选的Fault...
1. **SOAP Envelope**: 这是SOAP消息的基础结构,用于封装整个SOAP消息。在示例中,`<soap:Envelope>`标签就是SOAP信封,其中`xmlns:soap`定义了SOAP的命名空间。 2. **SOAP Encoding Style**: `soap:encodingStyle...
你需要提供SOAP消息的XML格式,包括方法名、参数等。例如: ```cpp qtsoap::SoapRequest request("http://example.com/service", "MethodName"); request.setParameter("Param1", "Value1"); request....