构建安全的Xml Web Service系列之如何察看SoapMessage

原文:构建安全的Xml Web Service系列之如何察看SoapMessage

上一篇文章地址:构建安全的Xml Web Service系列一之初探使用Soap头 (5-22 12:53)    
     要分析Xml Web Service的安全性,首先要解决的问题是我们能了解和清楚Soap消息的格式和内容,如果获得不了SoapMessage,分析如何能构建安全Xml web service也就无从下手,即使分析出来,自己也可 能模模糊糊,不能定论。下面就分析下如何获得SoapMessage。
    首先介绍一个类-SoapExtension,msdn对这个类的备注为:ASP.NET 允许通过扩展性机制生成与 SOAP 相关的基础结构。ASP.NET SOAP 扩展结构以一种扩展为中心,该扩展可以在客户端或服务器上处理消息时在特定阶段中检查或修改消息。ASP.NET SOAP 扩展从 SoapExtension 类派生。GetInitializer 和 Initialize 方法提供其他可用机制,用于初始化 SOAP 扩展以增强性能。ProcessMessage 是大多数 SOAP 扩展的核心,原因是该方法在 SoapMessageStage 中定义的每一个阶段都被调用,从而使 SOAP 扩展得以执行所需的该特定 SOAP 扩展的行为。对于需要修改 SOAP 请求或 SOAP 响应的 SOAP 扩展,ChainStream 提供一个机会以接收要通过网络发送的建议数据。 仔细阅读这段文字,如果您以前开发过windows程序,那第一个应该想到的是:原来web service的处理机制和windows窗口程序的消息机制竟然有着一曲同工之妙。下面谈谈如何利用这个类,来截获Xml web Service请求和相应的Soap消息,从而看看xml web service的庐山真面目。
    首先大家先看看这个类,这个类完成的功能是将Xml Web Service通过扩展的方式,将每次的请求和响应的Soap消息通过日志的方式保存到文本文件中。日志记录的方式也有两种:
    1。针对每个WebMethod产生一个日志文件。
    2。针对每个WebService产生一个日志文件
 因为一个WebService可能包含一个或者多个WebMethod,所以如果指定两种方法都支持的话,那第二个日志两面应该包括第一个日志里面的内容,而有些情况下,是不需要对每个WebMethod都进行日志记录的,这时候采用第一种记录方式,增强了系统的灵活性。 
下面是扩展了的SoapExtension

 <webServices>
        <soapExtensionTypes>
          <add type="Jillzhang.TraceExtension,Jillzhang" priority="1"  group="High"  />
        </soapExtensionTypes>
      </webServices>

可以记录SoapMessage的SoapExtension
namespace Jillzhang
{
    public class TraceExtension: SoapExtension
    {
        static readonly string LogRoot = System.Configuration.ConfigurationManager.AppSettings["logRoot"];
        Stream oldStream;
        Stream newStream;
        string filename;

       /// <summary>
       /// 将请求流和响应流存到内存流中,已被调用
       /// </summary>
        /// <param name="stream">包含 SOAP 请求或响应的内存缓冲区</param>
        /// <returns>它表示此 SOAP 扩展可以修改的新内存缓冲区。</returns>
        public override Stream ChainStream(Stream stream)
        {
            oldStream = stream;
            newStream = new MemoryStream();
            return newStream;
        }

        /// <summary>
        /// 在Xml Web Service第一次运行的时候,一次性的将通过TraceExtensionAttribute传递进来的
        /// 保存日志信息的文件名初始化
        /// </summary>
        /// <param name="methodInfo">应用 SOAP 扩展的 XML Web services 方法的特定函数原型</param>
        /// <param name="attribute">应用于 XML Web services 方法的 SoapExtensionAttribute</param>
        /// <returns>SOAP 扩展将对其进行初始化以用于缓存</returns>
        public override object GetInitializer(LogicalMethodInfo methodInfo, SoapExtensionAttribute attribute)
        {
            return ((TraceExtensionAttribute)attribute).Filename;
        }

        /// <summary>
        /// 替代为每个方法配置的保存SoapMessage文件名,而是将整个网络服务
        /// 的SoapMessage都保存到一个日志文件中,这个文件路径需要在Web Service
        /// 的配置文件中web.config指出,如
        /// <appSettings>
        ///  <add key="logRoot" value="c:\\serviceLog"/>
        /// </appSettings>
        /// </summary>
        /// <param name="WebServiceType">网络服务的类型</param>
        /// <returns>用于保存日志记录的文件路径</returns>
        public override object GetInitializer(Type WebServiceType)
        {
            //return LogRoot.TrimEnd(‘\\‘) + "\\" + WebServiceType.FullName + ".log";
            return LogRoot.TrimEnd(‘\\‘)+"\\"+ WebServiceType.FullName + ".log";
        }

        //获得文件名,并将其保存下来
        public override void Initialize(object initializer)
        {
            filename = (string)initializer;
        }

       /// <summary>
       /// 当数据还为Soap格式的时候,将数据写入日志
       /// </summary>
       /// <param name="message"></param>
        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");
            }
        }
        /// <summary>
        /// 将SoapMessage写入到日志文件
        /// </summary>
        /// <param name="message"></param>
        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) ? "Soap响应" : "Soap请求";
            w.WriteLine("-----" + soapString + " 在 " + DateTime.Now.ToString("yyyy年MM月dd日 HH时mm分ss秒"));
            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) ?
                 "Soap请求" : "Soap响应";
            w.WriteLine("-----" + soapString +
                " 在 " + DateTime.Now.ToString("yyyy年MM月dd日 HH时mm分ss秒"));
            w.Flush();
            newStream.Position = 0;
            Copy(newStream, fs);
            w.Close();
            newStream.Position = 0;
        }
        /// <summary>
        /// 拷贝流到流
        /// </summary>
        /// <param name="from"></param>
        /// <param name="to"></param>
        void Copy(Stream from, Stream to)
        {
            TextReader reader = new StreamReader(from);
            TextWriter writer = new StreamWriter(to);
            writer.WriteLine(reader.ReadToEnd());
            writer.Flush();
        }
    }

    //创建一个用于在WebMethod上使用的SoapExtension属性
    [AttributeUsage(AttributeTargets.Method)]
    public class TraceExtensionAttribute : SoapExtensionAttribute
    {

        private string filename = "c:\\log.txt";
        private int priority;

        /// <summary>
        /// 扩展类型
        /// </summary>
        public override Type ExtensionType
        {
            get { return typeof(TraceExtension); }
        }
        /// <summary>
        /// 优先级 
        /// </summary>
        public override int Priority
        {
            get { return priority; }
            set { priority = value; }
        }
        /// <summary>
        /// 用于记录该WebMethod的SoapMessage的文件的绝对路径
        /// 默认为c:\\log.txt;
        /// </summary>
        public string Filename
        {
            get
            {
                return filename;
            }
            set
            {
                filename = value;
            }
        }
    }   
}

结下来,介绍一个如何使用该类:
如果要使让TraceExtension支持第一种记录方式,需要作的额外工作为:
只需要在要记录SoapMessage的WebMethod添加如下的Attribute
[TraceExtension(Filename="d:\\data.xml",Priority=0)]
当然路径,您可以自己设定
前一节的WebMethod就变成了

添加了针对WebMethod日志记录的WebMethod
 public MySoapHeader header = new MySoapHeader();        
        [WebMethod]
        [SoapHeader("header")]   
        [TraceExtension(Filename="d:\\data.xml",Priority=0)]
        public string HelloWorld()
        {
            if (header == null)
            {
                return "您没有设置SoapHeader,不能正常访问此服务!";
            }
            if (header.UserName != "jillzhang" || header.Pwd != "123456")
            {
                return "您提供的身份验证信息有误,不能正常访问此服务!";
            }
            return "Hello World";
        }

调用下该WebService,便在d盘产生一个data.xml文件,里面的内容为:

日志记录
-----Soap请求 在 2007年05月25日 09时06分29秒
<?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><MySoapHeader xmlns="http://tempuri.org/"><UserName>jillzhang</UserName><Pwd>123456</Pwd></MySoapHeader></soap:Header><soap:Body><HelloWorld xmlns="http://tempuri.org/" /></soap:Body></soap:Envelope>


-----Soap响应 在 2007年05月25日 09时06分29秒
<?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><HelloWorldResponse xmlns="http://tempuri.org/"><HelloWorldResult>Hello World</HelloWorldResult></HelloWorldResponse></soap:Body></soap:Envelope>

如何采用第二种方法,让WebService的每个WebMethod都能记录日志
需要在Web.config中作如下的设定
首先添加如下节点

 <webServices>
        <soapExtensionTypes>
          <add type="Jillzhang.TraceExtension,Jillzhang" priority="1"  group="High"  />
        </soapExtensionTypes>
      </webServices>

然后通过配置设定日志文件保留的路径:

<appSettings>
    <add key="logRoot" value="d:"/>
  </appSettings>

找到日志文件,里面也赫然有着SoapMessage的真面目。通过以上方法,大家可以清晰地分析到SoapMessage的具体格式和内容,知道了这个以后,对付Web Service,您就可以随心应手,随心所欲,如果你愿意,你甚至也可以“强奸"一次webservice,哈哈!
上一篇文章地址:构建安全的Xml Web Service系列一之初探使用Soap头 (5-22 12:53)
附:终于买上房了,虽然买的过程很累,但现在还是很Happy!

时间: 2024-10-27 10:47:48

构建安全的Xml Web Service系列之如何察看SoapMessage的相关文章

构建安全的Xml Web Service系列之wse之证书存储位置

原文:构建安全的Xml Web Service系列之wse之证书存储位置 我们在前几天对xml web service的安全性提出了一些建议,大家可以通过以下地址访问: 构建安全的Xml Web Service系列之初探使用Soap头 构建安全的Xml Web Service系列之如何察看SoapMessage 构建安全的Xml Web Service系列之SSL篇 我曾经在上面几篇文章中承诺过要写一些有关wse3.0的,可一直没有时间,自身对wse3.0的认识也是非常有限,所以一直没有实现诺言

构建安全的Xml Web Service系列之初探使用Soap头

原文:构建安全的Xml Web Service系列之初探使用Soap头 Xml Web Service 从诞生那天就说自己都么都么好,还津津乐道的说internet也会因此而进入一个新纪元,可5年多来,Xml Web Service并没有像当初宣扬的那样火起来,尽管在一些领域之内,也有人牛刀小试,但从整体而言,Service还并没有得到广泛的应用,原因有很多,有一些来源于目前各大厂商都坚持自己的service标准,不能形成统一,也有对现有的稳定系统不愿进行更改的原因,但还包括web servic

构建安全的Xml Web Service系列之SSL篇

原文:构建安全的Xml Web Service系列之SSL篇 首先介绍一下SSL, SSL 的英文全称是 "Secure Sockets Layer" ,中文名为 "安全套接层协议层 ",它是网景( Netscape )公司提出的基于 WEB 应用的安全协议.SSL协议可分为两层: SSL记录协议(SSL Record Protocol):它建立在可靠的传输协议(如TCP)之上,为高层协议提供数据封装.压缩.加密等基本功能的支持.SSL是Security Socke

构建安全的Xml Web Service系列之wse之错误代码详解

原文:构建安全的Xml Web Service系列之wse之错误代码详解 WSE3.0现在还没有中文版的可以下载,使用英文版的过程中,难免会遇到各种各样的错误,而面对一堆毫无头绪的错误异常,常常会感到迷茫和无助,我起初就觉得这个框架使用起来真的很难用,有时候一些莫名其妙的错误会困扰我半天或者几天的时间,而一些英文的解释理解起来似是而非,很难一针见血的获得哪里出了问题,我将用几篇文章将wse所涉及到的错误代码和错误消息翻译成中文,并且根据个人的一点经验,提出引发错误的原因,并总结出解决建议,不是很

[Axis2与Eclipse整合开发Web Service系列之二] Top-Down方式,通过WSDL逆向生成服务端(续)

前言 本篇是承接上一篇: [Axis2与Eclipse整合开发Web Service系列之二] Top-Down方式,通过WSDL逆向生成服务端 在上一篇粗略地介绍了如何使用Top-Down的方式创建一个web service .  但是对于如何部署及调用,以及一些细节的部分基本上没有介绍. 应某些博友的要求, 也适逢自己有空, 接下来就详细介绍一下整个部分如何进行. 环境准备 JDK 肯定要安装了, 这个就不多讲了. 1. eclipse  3.5.2 对eclipse 版本的要求其实不是很严

[Axis2与Eclipse整合开发Web Service系列之三] 服务端返回值

前言 在前面的三篇中 [Axis2与Eclipse整合开发Web Service系列之一] 生成Web Service Client(将WSDl 转化成 Java代码) [Axis2与Eclipse整合开发Web Service系列之二] Top-Down方式,通过WSDL逆向生成服务端 [Axis2与Eclipse整合开发Web Service系列之二] Top-Down方式,通过WSDL逆向生成服务端(续) 介绍了如何使用 axis2 与 eclipse 的开发web Service .在第

XML Web Service:HTTP-GET, HTTP-POST and SOAP的比较

XML Web Service:HTTP-GET, HTTP-POST and SOAP的比较 XML Web Service支持三种协议来与用户交流数据.这三种协议分别是: 1. SOAP:Simple Object Access Protocol 2.  HTTP-GET 3.   HTTP-POST 1.首先我们先来理解一下这三者的大概定义. 在这三种协议中,SOAP是XML Web Service最常用到的连接协议.与HTTP相比,SOAP显的更为复杂,但却拥有更强的接受能力.SOAP是

XML Web Service初体验: HTTP-GET, HTTP-POST and SOAP的比较

.在ASP.NET 中,XML Web Service支持三种协议来与用户交流数据.这三种协议分别是: 1. SOAP:Simple Object Access Protocol 2.  HTTP-GET 3.   HTTP-POST 1.首先我们先来理解一下这三者的大概定义. 在这三种协议中,SOAP是XML Web Service最常用到的连接协议.与HTTP相比,SOAP显的更为复杂,但却拥有更强的接受能力.SOAP是一种以XML为基础的协议,它提供一种将数据打包(Packaging)和 

深入学习Web Service系列----异步开发模式

概述 在本篇随笔中,通过一些简单的示例来说一下Web Service中的异步调用模式.调用Web Service方法有两种方式,同步调用和异步调用.同步调用是程序继续执行前等候调用的完成,而异步调用在后台继续时,程序也继续执行,不必等待方法处理完成而直接返回.具体的调用流程见下图: 对于同步调用方法而言,UI线程依赖于方法的实现,方法执行时间过长将导致UI无法及时与用户进行交互.我们知道,在Windows客户端中,每个进程都有单一的UI进程,在服务器中,可扩展性依赖于线程的使用.对于异步调用方法