`
lzy.je
  • 浏览: 150765 次
  • 性别: Icon_minigender_1
  • 来自: 沈阳
社区版块
存档分类
最新评论

使用 .NET 调用有自定义 Handler 验证的 XFire Web 服务

阅读更多

          定义和使用 Web 服务都不是一件费力的事情,尤其在当前框架和工具的支持下更加容易。一般来说,常见情况下我们都会使用同一个开发语言、框架和工具来开发 Web 服务和调用服务的客户端。但是由于技术或非技术上的原因,又需要我们在不同的平台上发布、订阅彼此的 Web 服务。就在昨天,应同事的需要,就在 .NET 平台上使用 C# 编写一段调用部署在 XFire 上的 Web 服务的客户端代码。之前认为 Web 服务/SOAP 协议本来就是在开放的精神下设计的,因此跨平台调用也不会有多麻烦,但是也正是因为之前对 XFire 上的 Web 服务细节不太了解,浪费了我宝贵的几个小时,在此作以记录,另一方面也希望能为其它人提供些许帮助,免得大家无谓浪费时间。

 

          在这里要说明的是如何在 .NET (C#)代码中定义正确的 SOAP 头来满足 XFire Web 服务中使用自定义 Handler 验证操作 。这包括两种方式:

 

  1. 基于 .NET WCF 服务模型 的客户端服务代理。
  2. 基于 .NET Web 服务模型 的客户端服务代理。

话说两头,先表服务端。XFire Web 服务可以提供四种验证的方式,它们分别是:

 

  1. HTTP 验证
  2. JSR181 规范
  3. 自定义 Handler 代码
  4. WS-Security 规范

          在这里说的就是自定义 Handler 代码验证方式,当前 Web 服务中的 Handler 代码是根据 XFire 提供的示例代码改造的,很容易理解。

 

public class AuthenticationHandler extends AbstractHandler {

    // Namespace define, come from services.xml configuration.
    private final static Namespace TOKEN_NS = Namespace.getNamespace("demoService");

    public void invoke(MessageContext context) throws Exception {

        Element header = context.getInMessage().getHeader();
        
        if (header == null) {
            throw new XFireFault("Request must include company authentication token.", XFireFault.SENDER);
        }
        
        Element token = header.getChild("AuthenticationToken", TOKEN_NS);

        if (token == null) {
            throw new XFireFault("Request must include authentication token.", XFireFault.SENDER);
        }

        Element license = token.getChild("license", TOKEN_NS);
        
        if (license == null) {
            throw new XFireFault("license is null.", XFireFault.SENDER);
        }
        
        String licenseValue = license.getValue();
        
        if (licenseValue == null) {
            throw new XFireFault("license value is null.", XFireFault.SENDER);
        }

        try {
            // Other check code.
        } catch(Exception e) {
            throw new XFireFault("Authentication Failed.", XFireFault.SENDER);
        }
    }
}
 

          上面代码中有多步检查动作,其中关于内容检查的代码忽略了,留下的主要是对 SOAP 报文头中携带元素的存在性检查的代码。客户端调用要想通过该检查,首先要有 SOAP 头并携带必要的元素,其次才是元素内容正确。由于元素内容正确性检查涉及具体算法逻辑,这里就忽略不关注了。这里主要想说明是怎么保证 .NET 客户端发送 SOAP 报文头中携带必要的元素,根据上面代码可知,这里必须包括三部分:

 

  1. SOAP 报文必须有头信息
  2. 头中必须携带 AuthenticationToken 元素
  3. AuthenticationToken 元素中必须包括 license 子元素

另外要说明,AuthenticationHandler 类是在 services.xml 文件中配置生效的:

 

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

	<service>
		<name>demoService</name>
		<namespace>http://webservice.lzy.iteye.com</namespace>
		<serviceClass>com.lzy.javaeye.webservice.IWebService</serviceClass>
<implementationClass>com.lzy.javaeye.webservice.impl.WebService</implementationClass>
		<style>wrapped</style>
		<use>literal</use>  
        <scope>application</scope> 
		<inHandlers>
			<handler handlerClass="com.lzy.javaeye.webservice.AuthenticationHandler"/>
		</inHandlers>       
	</service>
</beans>
 

          其中配置的 inHandlers 元素就是为 demoService 服务的添加了自定义 Handler 验证,即 AuthenticationHandler 类。

 

          服务端就是上面这些,下面就要分两方面(WCF 服务模型和 Web 服务模型)来说明 .NET调用的事了。

 

          先说在 .NET 中通过 WCF 服务框架调用 XFire Web 服务。 在 .NET 3.5 中微软提出了 WCF 框架,在这种基于服务的通信框架中包括了很多概念,契约就是重要的一个。WCF 将所有服务都定义为契约,它与平台无关,是描述服务功能的标准方式。WCF 契约分为四种:

  1. 服务契约(Service Contract)
  2. 数据契约(Data Contract)
  3. 错误契约(Fault Contract)
  4. 消息契约(Message Contract)

          结合这个场景来说吧,调用一次服务,对于 WCF 来说属于使用规范的消息契约和定义的服务契约进行一次通信,因此 SOAP 报文本身属于消息契约,同时该消息契约内要包括一个头对象 AuthenticationToken(使用 System.ServiceModel.MessageHeaderAttribute 属性修饰),另外这个 AuthenticationToken 对象还应该是一个数据契约(使用 DataContractAttribute 属性修饰)。定义 SOAP 头的消息契约类代码如下,这个实际是扩展自 Visual Studio 的 Services 引用向导生成的 partial 类。

 

public partial class serviceMethodRequest
{
    [System.ServiceModel.MessageHeaderAttribute(Name = "AuthenticationToken", Namespace = "demoService")]
    public DemoSoapHeader SoapHeader = new DemoSoapHeader();
} 

 

          需要注意的是其中 Namespace 参数与 WSDL 中定义的服务命名空间要对应,之前这个事就把我搞得头痛,还要感谢 Fiddler。再看看那个数据契约类代码,和上面是对应的。

 

[System.Runtime.Serialization.DataContractAttribute(Namespace = "demoService")]
[Serializable]
public class DemoSoapHeader
{
    [System.Runtime.Serialization.DataMember()]
    public string license = null;
}
 

          剩下就是实例化客户端本地服务代理、实例化消息契约类、实例化并设置 SOAP 头数据契约类,调用等等正常走流程吧。

 

          接下来说在 .NET 中通过 “传统”(是 2.0 时的经典方法吧,呵呵) Web 服务框架调用 XFire Web 服务。 其实这种方式在网上文档很多,这里也不想再重复。主要就是首先定义一个表式 SOAP 头的对象:

 

[System.Serializable]
[System.Xml.Serialization.XmlType(Namespace = "demoService")]
[System.Xml.Serialization.XmlRoot(Namespace = "demoService", IsNullable = false)]
public class AuthenticationToken : SoapHeader
{
    public string license = null;
}

 

          这里需要注意的就是类的名称 AuthenticationToken 就是 SOAP 报文中节点的名称,在这里和 WCF 中可配置的方式有些不同。然后扩展 Visual Studio 的 Web 引用向导生成的 partial 类,添加一个用来表示 SOAP 头中数据节点的成员对象:

 

public partial class DemoService
{
    public AuthenticationToken SoapHeader = new AuthenticationToken();
}

 

          最重要的是,还需要在 WebMethod 方法上添加属性,该方法位于 Visual Studio 的 Web 引用向导生成的服务代理类,指定 SOAP 头中携带对象元素所关联的成员变量:

 

[SoapHeader("SoapHeader")]
public OutEntBaseBean findEntBase([System.Xml.Serialization.XmlElementAttribute(IsNullable=true)] ParamClass in0)
{
    // Invok code.
}

 

          这里比较有趣的是,使用 WCF 服务模型来编写时,可以看到不需要修改 Visual Studio 引用向导生成的本地服务代理类中的代码,而使用 Web 服务模型时却需要在 WebMethod 上添加 SoapHeader 标签,这意味着使用后者时,只要在 Visual Studio 中刷新引用的服务时,都要重写添加所有更改过的代码,这个就比较郁闷了。

 

          最后调用服务的方法相对使用 WCF 服务模型简单一些,实例化客户端本地服务代理、实例化并设置 SOAP 头对象、调用等等吧。

 

最后把 SOAP 报文也贴上来吧,首先是 WCF 服务模型生成的报文:

 

<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
  <s:Header>
    <h:AuthenticationToken xmlns:h="demoService" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
      <h:license>This is license.</h:license>
    </h:AuthenticationToken>
  </s:Header>
  <s:Body>

  </s:Body>
</s:Envelope>
 

接下来这个是  Web 服务模型生成的报文:

 

<?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:Header>
    <AuthenticationToken xmlns="demoService">
      <license>This is license.</license>
    </AuthenticationToken>
  </soap:Header>
  <soap:Body>

  </soap:Body>
</soap:Envelope>
 

上面的 Body 内容省略了。

 

          就是以上这些了,实际这里涉及的内容是很简单的,但当真正做这件简单的事情时却也浪费了一些时间,在此做以记录备忘吧。欢迎大家一起讨论、提高。

 

注明:以上所有内容和代码,如与我有关项目或文档有相似之处纯属巧合。

 

// 2009.01.05 20:55 添加 ////

 

巧了,看来“头”的问题很重要啊,呵呵。

java axis调用带有soap头(soapheader)的.net webservice

 

// 2009.02.06 16:48 添加 ////

 

附件 MdmSvcCallee.zip 为备份目的所添加,请勿下载使用。

 

// 2009.03.07 13:30 添加 ////


作者:lzy.je
出处:http://lzy.iteye.com
本文版权归作者所有,只允许以摘要和完整全文两种形式转载,不允许对文字进行裁剪。未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

 

6
0
分享到:
评论
12 楼 bhc1978 2012-08-02  
怎么还搞了个密码啊
11 楼 lzy.je 2009-08-20  
micropang 写道
老兄真是服了你了~~
怎么就不能贴个完整的客户端代码出来嗫?~~


你没看到附件么?晕~
10 楼 micropang 2009-08-20  
老兄真是服了你了~~
怎么就不能贴个完整的客户端代码出来嗫?~~

看了这些,很费解,心肌梗塞啊~~
如果楼主方便,麻烦发一份到邮箱,谢谢:pangsirsky@163.com
9 楼 ajjjian 2008-12-16  
lzy.je 写道

ajjjian 写道
lzy.je 写道ajjjian 写道lzy.je 写道1. AuthenticationToken 类是自己定义的。2. DemoService 是一个 partal 类,主要的代码是由 Visual Stuio 的 Web 引用向导生成的,而本文中给出的代码片段是自己定义的,用来添加表示 SOAP 头所必要的成员变量。我用的是vs2005直接添加web引用是并不会生成什么partal类我印象里在 Visual Stuio 2005 里已经有 partal 类了,在网上查了一下。这里的 partal 是 C# 2.0 里加的新特征,不是类的名子是“partal”。您误会我的意思了,我的意思是我找不到DemoService类(同级别)的代码,我这边生成的webservice没有任何可以看到有代码的类,只有一个.discomap和一个..wsdl文件。另外您说的:“最重要的是,还需要在 WebMethod 方法上添加属性,该方法位于 Visual Studio 的 Web 引用向导生成的服务代理类,指定 SOAP 头中携带对象元素所关联的成员变量:”,这个服务代理类也是看不到代码的。

我明白你的意思了,Sorry。是这样,我的一位同事在很早先也遇到和你同样的问题,和他沟通了下,当时他是通过调整 XFire 中的一个配置文件,添加一个配置项解决的,不过由于时间长了,他现在也记不得了。现在我这里没法验证你的问题,没有环境。


哦。明白了,十分感谢您的耐心解释。
8 楼 lzy.je 2008-12-16  
ajjjian 写道

lzy.je 写道
ajjjian 写道
lzy.je 写道1. AuthenticationToken 类是自己定义的。2. DemoService 是一个 partal 类,主要的代码是由 Visual Stuio 的 Web 引用向导生成的,而本文中给出的代码片段是自己定义的,用来添加表示 SOAP 头所必要的成员变量。我用的是vs2005直接添加web引用是并不会生成什么partal类我印象里在 Visual Stuio 2005 里已经有 partal 类了,在网上查了一下。这里的 partal 是 C# 2.0 里加的新特征,不是类的名子是“partal”。

您误会我的意思了,我的意思是我找不到DemoService类(同级别)的代码,我这边生成的webservice没有任何可以看到有代码的类,只有一个.discomap和一个..wsdl文件。另外您说的:“最重要的是,还需要在 WebMethod 方法上添加属性,该方法位于 Visual Studio 的 Web 引用向导生成的服务代理类,指定 SOAP 头中携带对象元素所关联的成员变量:”,这个服务代理类也是看不到代码的。


我明白你的意思了,Sorry。是这样,我的一位同事在很早先也遇到和你同样的问题,和他沟通了下,当时他是通过调整 XFire 中的一个配置文件,添加一个配置项解决的,不过由于时间长了,他现在也记不得了。现在我这里没法验证你的问题,没有环境。
7 楼 ajjjian 2008-12-16  
lzy.je 写道

ajjjian 写道
lzy.je 写道1. AuthenticationToken 类是自己定义的。2. DemoService 是一个 partal 类,主要的代码是由 Visual Stuio 的 Web 引用向导生成的,而本文中给出的代码片段是自己定义的,用来添加表示 SOAP 头所必要的成员变量。我用的是vs2005直接添加web引用是并不会生成什么partal类我印象里在 Visual Stuio 2005 里已经有 partal 类了,在网上查了一下。这里的 partal 是 C# 2.0 里加的新特征,不是类的名子是“partal”。

您误会我的意思了,我的意思是我找不到DemoService类(同级别)的代码,我这边生成的webservice没有任何可以看到有代码的类,只有一个.discomap和一个..wsdl文件。另外您说的:“最重要的是,还需要在 WebMethod 方法上添加属性,该方法位于 Visual Studio 的 Web 引用向导生成的服务代理类,指定 SOAP 头中携带对象元素所关联的成员变量:”,这个服务代理类也是看不到代码的。
6 楼 lzy.je 2008-12-15  
ajjjian 写道

C#代码 &nbsp;&nbsp;最重要的是,还需要在&nbsp;WebMethod&nbsp;方法上添加属性,该方法位于&nbsp;Visual&nbsp;Studio&nbsp;的&nbsp;Web&nbsp;引用向导生成的服务代理类,指定&nbsp;SOAP&nbsp;头中携带对象元素所关联的成员变量:&nbsp;&nbsp;&nbsp;&nbsp;C#代码&nbsp;&nbsp;&nbsp;[SoapHeader("SoapHeader")]&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;OutEntBaseBean&nbsp;findEntBase([System.Xml.Serialization.XmlElementAttribute(IsNullable=true)]&nbsp;ParamClass&nbsp;in0)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;Invok&nbsp;code.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;&nbsp;&nbsp;  最重要的是,还需要在 WebMethod 方法上添加属性,该方法位于 Visual Studio 的 Web 引用向导生成的服务代理类,指定 SOAP 头中携带对象元素所关联的成员变量:

C#代码
[SoapHeader("SoapHeader")]  
public OutEntBaseBean findEntBase([System.Xml.Serialization.XmlElementAttribute(IsNullable=true)] ParamClass in0)  
{  
    // Invok code.  



以上代码是服务端,还是客户端的
再问一下,你是不是.net调用java服务端提供的webservise


正象标题所述,是使用 .NET 开发客户端调用部署在 XFire 上的 Web 服务。
5 楼 lzy.je 2008-12-15  
ajjjian 写道

lzy.je 写道
1. AuthenticationToken 类是自己定义的。2. DemoService 是一个 partal 类,主要的代码是由 Visual Stuio 的 Web 引用向导生成的,而本文中给出的代码片段是自己定义的,用来添加表示 SOAP 头所必要的成员变量。

我用的是vs2005直接添加web引用是并不会生成什么partal类


我印象里在 Visual Stuio 2005 里已经有 partal 类了,在网上查了一下。这里的 partal 是 C# 2.0 里加的新特征,不是类的名子是“partal”。
4 楼 ajjjian 2008-12-15  
lzy.je 写道

1. AuthenticationToken 类是自己定义的。2. DemoService 是一个 partal 类,主要的代码是由 Visual Stuio 的 Web 引用向导生成的,而本文中给出的代码片段是自己定义的,用来添加表示 SOAP 头所必要的成员变量。


我用的是vs2005直接添加web引用是并不会生成什么partal类

3 楼 lzy.je 2008-12-15  
ajjjian 写道

引用:在你的文章中提到如下:
&nbsp; 1.这里需要注意的就是类的名称 AuthenticationToken 就是 SOAP 报文中节点的名称,在这里和 WCF 中可配置的方式有些不同。然后扩展 Visual Studio 的 Web 引用向导生成的 partal 类,添加一个用来表示 SOAP 头中数据节点的成员对象:
&nbsp;&nbsp;&nbsp; public partial class DemoService
&nbsp;&nbsp;
&nbsp; 问:
&nbsp;&nbsp; 这个类对象是你自己创建的,还是客户端WEB引用时自动生成的。
&nbsp;&nbsp; 如可以的话,发我一份你的Demo.非常感谢!!!
&nbsp;&nbsp; email:chenbin01234@tom.com


1. AuthenticationToken 类是自己定义的。
2. DemoService 是一个 partal 类,主要的代码是由 Visual Stuio 的 Web 引用向导生成的,而本文中给出的代码片段是自己定义的,用来添加表示 SOAP 头所必要的成员变量。
2 楼 ajjjian 2008-12-15  
  最重要的是,还需要在 WebMethod 方法上添加属性,该方法位于 Visual Studio 的 Web 引用向导生成的服务代理类,指定 SOAP 头中携带对象元素所关联的成员变量:

C#代码 
[SoapHeader("SoapHeader")]   
public OutEntBaseBean findEntBase([System.Xml.Serialization.XmlElementAttribute(IsNullable=true)] ParamClass in0)   
{   
    // Invok code.   
}  



以上代码是服务端,还是客户端的
再问一下,你是不是.net调用java服务端提供的webservise
1 楼 ajjjian 2008-12-15  
引用:在你的文章中提到如下:
  1.这里需要注意的就是类的名称 AuthenticationToken 就是 SOAP 报文中节点的名称,在这里和 WCF 中可配置的方式有些不同。然后扩展 Visual Studio 的 Web 引用向导生成的 partal 类,添加一个用来表示 SOAP 头中数据节点的成员对象:
    public partial class DemoService
  
  问:
   这个类对象是你自己创建的,还是客户端WEB引用时自动生成的。
   如可以的话,发我一份你的Demo.非常感谢!!!
   email:chenbin01234@tom.com

相关推荐

    ASP.NET源码——利用handler生成静态页面的完整解决方案.zip

    ASP.NET 是微软开发的一种用于构建Web应用程序的框架,它提供了丰富的功能和强大的工具来帮助开发者创建动态、数据驱动的网站。在这个"ASP.NET源码——利用handler生成静态页面的完整解决方案.zip"压缩包中,我们...

    自定义Handler-Looper实现线程间通信

    在Android系统中,主线程默认已经有一个运行的Looper,但如果我们需要在自定义线程中使用Handler进行消息通信,就需要手动创建并启动Looper。这是通过调用Looper.prepare()初始化Looper,然后调用Looper.loop()进入...

    asp.net mvc handler

    ASP.NET MVC Handler 是微软开发的一种Web应用程序框架,用于构建可维护性和可测试性极高的Web应用。这个框架基于模型-视图-控制器(MVC)设计模式,它为开发者提供了更多的控制力和灵活性,使他们能够更高效地构建...

    自定义Handler

    为了在自定义线程中使用`Handler`,你需要先调用`Looper.prepare()`初始化`Looper`,然后调用`Looper.loop()`开始消息循环。 `MessageQueue`是消息队列,它存储了待处理的消息。`Looper`会不断从`MessageQueue`中...

    httpHandler实现.Net无后缀名Web访问

    通过以上步骤,我们可以实现在.NET环境中使用自定义HTTP Handler来处理无后缀名的URL请求。这种方法不仅提高了用户体验,还使得Web应用程序更加灵活和高效。需要注意的是,对于不同的.NET版本或IIS版本,具体的配置...

    asp.net+jquery+ajax所有调用例子

    此外,ASP.NET还支持通过Web服务(WebService)进行AJAX调用。创建一个ASMX文件,定义一个Web方法: ```csharp [WebService(Namespace = "http://tempuri.org/")] [WebServiceBinding(ConformsTo = WsiProfiles....

    ASP.Net中自定义Http处理及其应用

    ASP.NET 是微软开发的一种Web应用程序框架,用于构建动态网站、Web应用程序和服务。在ASP.NET中,自定义HTTP处理是扩展其功能和控制请求处理流程的关键技术。本文将深入探讨自定义HTTP处理,包括HTTP Handler...

    WebApi系列-通过HttpClient来调用WebApi接口.doc

    本文将详细介绍如何使用`HttpClient`来调用Web API接口。 #### 二、HttpClient简介 `HttpClient`是一个被广泛使用的类,用于发起HTTP请求并接收响应。它在.NET框架中得到了很好的支持和封装。与其他语言如Java或...

    asp.net(c#)实现在线拍照上传

    ASP.NET(C#)在线拍照上传是一个常见的功能需求,尤其在在线教育、远程认证和考试系统等场景中。本文将详细解析如何利用ASP.NET和C#实现这一功能,结合Flash和摄像头技术,创建一个实时拍照并上传的系统。 首先,...

    使用XFire+Spring构建Web Service

    【使用XFire+Spring构建Web Service】是一种在Java平台上开发Web服务的高效方法。XFire作为新一代的Web服务框架,与Axis2并列,因其简洁的API和对Web服务标准的良好支持而受到开发者欢迎。XFire特别强调与Spring框架...

    nginx源码vs工程-自定义handler处理-创建子请求处理逻辑-filter过滤器中处理应答

    自定义handler进入方式可以修改,即可以从location中读取关键字,也可以从请求头中检测是否有对应字段。 (此处从请求头中检测是否有对应字段,有则进入处理,否则往下一阶段处理) 7.添加cJson库解析处理接收到...

    使用xfire框架搭建webService的一个demo

    总的来说,xfireDemo项目演示了如何在xfire框架下实现两种不同方式的身份验证机制,这对于理解Web服务的安全性和xfire的使用是非常有价值的。通过这个示例,开发者可以学习到如何在实际项目中应用这些技术,增强Web...

    ASP.NET-[其他类别]利用handler生成静态页面的完整解决方案v1.1.zip

    与传统的ASP.NET页面(如.aspx)不同,Handler不依赖于ASP.NET生命周期,因此它能够提供更高效的服务。在高流量的网站中,生成静态页面可以显著减少服务器的工作量,因为静态HTML不需要执行任何服务器端代码或数据库...

    .NET C# ASP.NET 文字转语音.zip

    在.NET框架中,C#和ASP.NET结合使用可以创建丰富的Web应用程序。在这个特定的".NET C# ASP.NET 文字转语音.zip"项目中,开发者利用了Text-to-Speech(TTS)技术,将文字转化为可听的语音。这种技术在各种应用场景中...

    整理xfire和spring的集成 web service 面向服务编程 java

    将两者集成可以方便地构建和消费Web Service,实现服务的发布和调用。下面将详细介绍如何在Java项目中整合XFire和Spring。 ### 1. 项目准备 首先,确保项目中包含了必要的jar包。XFire的集成通常需要以下几类库: ...

    .net自定义事件编程

    在.NET中,通常使用`EventHandler&lt;TEventArgs&gt;`或`EventHandler`(当不需要传递自定义参数时)作为事件的委托类型。例如,`public event EventHandler MyEvent;` 2. **事件访问器(Event Accessors)** - `add`和`...

Global site tag (gtag.js) - Google Analytics