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

简介: 原文:构建安全的Xml Web Service系列之如何察看SoapMessage    上一篇文章地址:构建安全的Xml Web Service系列一之初探使用Soap头 (5-22 12:53)          要分析Xml Web Service的安全性,首先要解决的问题是我们能了解和清楚Soap消息的格式和内容,如果获得不了SoapMessage,分析如何能构建安全Xml web service也就无从下手,即使分析出来,自己也可 能模模糊糊,不能定论。
原文: 构建安全的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

img_a6339ee3e57d1d52bc7d02b338e15a60.gif   < webServices >
img_a6339ee3e57d1d52bc7d02b338e15a60.gif        
< soapExtensionTypes >
img_a6339ee3e57d1d52bc7d02b338e15a60.gif          
< add  type ="Jillzhang.TraceExtension,Jillzhang"  priority ="1"   group ="High"    />
img_a6339ee3e57d1d52bc7d02b338e15a60.gif        
</ soapExtensionTypes >
img_a6339ee3e57d1d52bc7d02b338e15a60.gif      
</ webServices >
img_1c53668bcee393edac0d7b3b3daff1ae.gif img_405b18b4b6584ae338e0f6ecaf736533.gif 可以记录SoapMessage的SoapExtension
img_a6339ee3e57d1d52bc7d02b338e15a60.gifnamespace Jillzhang
img_a6339ee3e57d1d52bc7d02b338e15a60.gif{
img_a6339ee3e57d1d52bc7d02b338e15a60.gif    public class TraceExtension: SoapExtension
img_a6339ee3e57d1d52bc7d02b338e15a60.gif    {
img_a6339ee3e57d1d52bc7d02b338e15a60.gif        static readonly string LogRoot = System.Configuration.ConfigurationManager.AppSettings["logRoot"];
img_a6339ee3e57d1d52bc7d02b338e15a60.gif        Stream oldStream;
img_a6339ee3e57d1d52bc7d02b338e15a60.gif        Stream newStream;
img_a6339ee3e57d1d52bc7d02b338e15a60.gif        string filename;
img_a6339ee3e57d1d52bc7d02b338e15a60.gif
img_a6339ee3e57d1d52bc7d02b338e15a60.gif       /// 
<summary>
img_a6339ee3e57d1d52bc7d02b338e15a60.gif       /// 将请求流和响应流存到内存流中,已被调用
img_a6339ee3e57d1d52bc7d02b338e15a60.gif       /// 
</summary>
img_a6339ee3e57d1d52bc7d02b338e15a60.gif        /// 
<param name="stream">包含 SOAP 请求或响应的内存缓冲区</param>
img_a6339ee3e57d1d52bc7d02b338e15a60.gif        /// 
<returns>它表示此 SOAP 扩展可以修改的新内存缓冲区。</returns>
img_a6339ee3e57d1d52bc7d02b338e15a60.gif        public override Stream ChainStream(Stream stream)
img_a6339ee3e57d1d52bc7d02b338e15a60.gif        {
img_a6339ee3e57d1d52bc7d02b338e15a60.gif            oldStream = stream;
img_a6339ee3e57d1d52bc7d02b338e15a60.gif            newStream = new MemoryStream();
img_a6339ee3e57d1d52bc7d02b338e15a60.gif            return newStream;
img_a6339ee3e57d1d52bc7d02b338e15a60.gif        }
img_a6339ee3e57d1d52bc7d02b338e15a60.gif
img_a6339ee3e57d1d52bc7d02b338e15a60.gif        /// 
<summary>
img_a6339ee3e57d1d52bc7d02b338e15a60.gif        /// 在Xml Web Service第一次运行的时候,一次性的将通过TraceExtensionAttribute传递进来的
img_a6339ee3e57d1d52bc7d02b338e15a60.gif        /// 保存日志信息的文件名初始化
img_a6339ee3e57d1d52bc7d02b338e15a60.gif        /// 
</summary>
img_a6339ee3e57d1d52bc7d02b338e15a60.gif        /// 
<param name="methodInfo">应用 SOAP 扩展的 XML Web services 方法的特定函数原型</param>
img_a6339ee3e57d1d52bc7d02b338e15a60.gif        /// 
<param name="attribute">应用于 XML Web services 方法的 SoapExtensionAttribute</param>
img_a6339ee3e57d1d52bc7d02b338e15a60.gif        /// 
<returns>SOAP 扩展将对其进行初始化以用于缓存</returns>
img_a6339ee3e57d1d52bc7d02b338e15a60.gif        public override object GetInitializer(LogicalMethodInfo methodInfo, SoapExtensionAttribute attribute)
img_a6339ee3e57d1d52bc7d02b338e15a60.gif        {
img_a6339ee3e57d1d52bc7d02b338e15a60.gif            return ((TraceExtensionAttribute)attribute).Filename;
img_a6339ee3e57d1d52bc7d02b338e15a60.gif        }
img_a6339ee3e57d1d52bc7d02b338e15a60.gif
img_a6339ee3e57d1d52bc7d02b338e15a60.gif        /// 
<summary>
img_a6339ee3e57d1d52bc7d02b338e15a60.gif        /// 替代为每个方法配置的保存SoapMessage文件名,而是将整个网络服务
img_a6339ee3e57d1d52bc7d02b338e15a60.gif        /// 的SoapMessage都保存到一个日志文件中,这个文件路径需要在Web Service
img_a6339ee3e57d1d52bc7d02b338e15a60.gif        /// 的配置文件中web.config指出,如
img_a6339ee3e57d1d52bc7d02b338e15a60.gif        /// 
<appSettings>
img_a6339ee3e57d1d52bc7d02b338e15a60.gif        ///  
<add key="logRoot" value="c:\\serviceLog"/>
img_a6339ee3e57d1d52bc7d02b338e15a60.gif        /// 
</appSettings>
img_a6339ee3e57d1d52bc7d02b338e15a60.gif        /// 
</summary>
img_a6339ee3e57d1d52bc7d02b338e15a60.gif        /// 
<param name="WebServiceType">网络服务的类型</param>
img_a6339ee3e57d1d52bc7d02b338e15a60.gif        /// 
<returns>用于保存日志记录的文件路径</returns>
img_a6339ee3e57d1d52bc7d02b338e15a60.gif        public override object GetInitializer(Type WebServiceType)
img_a6339ee3e57d1d52bc7d02b338e15a60.gif        {
img_a6339ee3e57d1d52bc7d02b338e15a60.gif            //return LogRoot.TrimEnd('\\') + "\\" + WebServiceType.FullName + ".log";
img_a6339ee3e57d1d52bc7d02b338e15a60.gif            return LogRoot.TrimEnd('\\')+"\\"+ WebServiceType.FullName + ".log";
img_a6339ee3e57d1d52bc7d02b338e15a60.gif        }
img_a6339ee3e57d1d52bc7d02b338e15a60.gif
img_a6339ee3e57d1d52bc7d02b338e15a60.gif        //获得文件名,并将其保存下来
img_a6339ee3e57d1d52bc7d02b338e15a60.gif        public override void Initialize(object initializer)
img_a6339ee3e57d1d52bc7d02b338e15a60.gif        {
img_a6339ee3e57d1d52bc7d02b338e15a60.gif            filename = (string)initializer;
img_a6339ee3e57d1d52bc7d02b338e15a60.gif        }
img_a6339ee3e57d1d52bc7d02b338e15a60.gif
img_a6339ee3e57d1d52bc7d02b338e15a60.gif       /// 
<summary>
img_a6339ee3e57d1d52bc7d02b338e15a60.gif       /// 当数据还为Soap格式的时候,将数据写入日志
img_a6339ee3e57d1d52bc7d02b338e15a60.gif       /// 
</summary>
img_a6339ee3e57d1d52bc7d02b338e15a60.gif       /// 
<param name="message"></param>
img_a6339ee3e57d1d52bc7d02b338e15a60.gif        public override void ProcessMessage(SoapMessage message)
img_a6339ee3e57d1d52bc7d02b338e15a60.gif        {
img_a6339ee3e57d1d52bc7d02b338e15a60.gif            switch (message.Stage)
img_a6339ee3e57d1d52bc7d02b338e15a60.gif            {
img_a6339ee3e57d1d52bc7d02b338e15a60.gif                case SoapMessageStage.BeforeSerialize:
img_a6339ee3e57d1d52bc7d02b338e15a60.gif                    break;
img_a6339ee3e57d1d52bc7d02b338e15a60.gif                case SoapMessageStage.AfterSerialize:
img_a6339ee3e57d1d52bc7d02b338e15a60.gif                    WriteOutput(message);
img_a6339ee3e57d1d52bc7d02b338e15a60.gif                    break;
img_a6339ee3e57d1d52bc7d02b338e15a60.gif                case SoapMessageStage.BeforeDeserialize:
img_a6339ee3e57d1d52bc7d02b338e15a60.gif                    WriteInput(message);
img_a6339ee3e57d1d52bc7d02b338e15a60.gif                    break;
img_a6339ee3e57d1d52bc7d02b338e15a60.gif                case SoapMessageStage.AfterDeserialize:
img_a6339ee3e57d1d52bc7d02b338e15a60.gif                    break;
img_a6339ee3e57d1d52bc7d02b338e15a60.gif                default:
img_a6339ee3e57d1d52bc7d02b338e15a60.gif                    throw new Exception("invalid stage");
img_a6339ee3e57d1d52bc7d02b338e15a60.gif            }
img_a6339ee3e57d1d52bc7d02b338e15a60.gif        }
img_a6339ee3e57d1d52bc7d02b338e15a60.gif        /// 
<summary>
img_a6339ee3e57d1d52bc7d02b338e15a60.gif        /// 将SoapMessage写入到日志文件
img_a6339ee3e57d1d52bc7d02b338e15a60.gif        /// 
</summary>
img_a6339ee3e57d1d52bc7d02b338e15a60.gif        /// 
<param name="message"></param>
img_a6339ee3e57d1d52bc7d02b338e15a60.gif        public void WriteOutput(SoapMessage message)
img_a6339ee3e57d1d52bc7d02b338e15a60.gif        {
img_a6339ee3e57d1d52bc7d02b338e15a60.gif            newStream.Position = 0; 
img_a6339ee3e57d1d52bc7d02b338e15a60.gif            //创建或追加记录文件
img_a6339ee3e57d1d52bc7d02b338e15a60.gif            FileStream fs = new FileStream(filename, FileMode.Append,
img_a6339ee3e57d1d52bc7d02b338e15a60.gif                FileAccess.Write);
img_a6339ee3e57d1d52bc7d02b338e15a60.gif            StreamWriter w = new StreamWriter(fs);
img_a6339ee3e57d1d52bc7d02b338e15a60.gif            string soapString = (message is SoapServerMessage) ? "Soap响应" : "Soap请求";
img_a6339ee3e57d1d52bc7d02b338e15a60.gif            w.WriteLine("-----" + soapString + " 在 " + DateTime.Now.ToString("yyyy年MM月dd日 HH时mm分ss秒"));
img_a6339ee3e57d1d52bc7d02b338e15a60.gif            w.Flush();
img_a6339ee3e57d1d52bc7d02b338e15a60.gif            Copy(newStream, fs);
img_a6339ee3e57d1d52bc7d02b338e15a60.gif            w.Close();
img_a6339ee3e57d1d52bc7d02b338e15a60.gif            newStream.Position = 0;
img_a6339ee3e57d1d52bc7d02b338e15a60.gif            Copy(newStream, oldStream);
img_a6339ee3e57d1d52bc7d02b338e15a60.gif        }
img_a6339ee3e57d1d52bc7d02b338e15a60.gif
img_a6339ee3e57d1d52bc7d02b338e15a60.gif        public void WriteInput(SoapMessage message)
img_a6339ee3e57d1d52bc7d02b338e15a60.gif        {
img_a6339ee3e57d1d52bc7d02b338e15a60.gif            Copy(oldStream, newStream);
img_a6339ee3e57d1d52bc7d02b338e15a60.gif            FileStream fs = new FileStream(filename, FileMode.Append,
img_a6339ee3e57d1d52bc7d02b338e15a60.gif                FileAccess.Write);
img_a6339ee3e57d1d52bc7d02b338e15a60.gif            StreamWriter w = new StreamWriter(fs);
img_a6339ee3e57d1d52bc7d02b338e15a60.gif
img_a6339ee3e57d1d52bc7d02b338e15a60.gif            string soapString = (message is SoapServerMessage) ?
img_a6339ee3e57d1d52bc7d02b338e15a60.gif                 "Soap请求" : "Soap响应";
img_a6339ee3e57d1d52bc7d02b338e15a60.gif            w.WriteLine("-----" + soapString +
img_a6339ee3e57d1d52bc7d02b338e15a60.gif                " 在 " + DateTime.Now.ToString("yyyy年MM月dd日 HH时mm分ss秒"));
img_a6339ee3e57d1d52bc7d02b338e15a60.gif            w.Flush();
img_a6339ee3e57d1d52bc7d02b338e15a60.gif            newStream.Position = 0;
img_a6339ee3e57d1d52bc7d02b338e15a60.gif            Copy(newStream, fs);
img_a6339ee3e57d1d52bc7d02b338e15a60.gif            w.Close();
img_a6339ee3e57d1d52bc7d02b338e15a60.gif            newStream.Position = 0;
img_a6339ee3e57d1d52bc7d02b338e15a60.gif        }
img_a6339ee3e57d1d52bc7d02b338e15a60.gif        /// 
<summary>
img_a6339ee3e57d1d52bc7d02b338e15a60.gif        /// 拷贝流到流
img_a6339ee3e57d1d52bc7d02b338e15a60.gif        /// 
</summary>
img_a6339ee3e57d1d52bc7d02b338e15a60.gif        /// 
<param name="from"></param>
img_a6339ee3e57d1d52bc7d02b338e15a60.gif        /// 
<param name="to"></param>
img_a6339ee3e57d1d52bc7d02b338e15a60.gif        void Copy(Stream from, Stream to)
img_a6339ee3e57d1d52bc7d02b338e15a60.gif        {
img_a6339ee3e57d1d52bc7d02b338e15a60.gif            TextReader reader = new StreamReader(from);
img_a6339ee3e57d1d52bc7d02b338e15a60.gif            TextWriter writer = new StreamWriter(to);
img_a6339ee3e57d1d52bc7d02b338e15a60.gif            writer.WriteLine(reader.ReadToEnd());
img_a6339ee3e57d1d52bc7d02b338e15a60.gif            writer.Flush();
img_a6339ee3e57d1d52bc7d02b338e15a60.gif        }
img_a6339ee3e57d1d52bc7d02b338e15a60.gif    }
img_a6339ee3e57d1d52bc7d02b338e15a60.gif
img_a6339ee3e57d1d52bc7d02b338e15a60.gif    //创建一个用于在WebMethod上使用的SoapExtension属性
img_a6339ee3e57d1d52bc7d02b338e15a60.gif    [AttributeUsage(AttributeTargets.Method)]
img_a6339ee3e57d1d52bc7d02b338e15a60.gif    public class TraceExtensionAttribute : SoapExtensionAttribute
img_a6339ee3e57d1d52bc7d02b338e15a60.gif    {
img_a6339ee3e57d1d52bc7d02b338e15a60.gif
img_a6339ee3e57d1d52bc7d02b338e15a60.gif        private string filename = "c:\\log.txt";
img_a6339ee3e57d1d52bc7d02b338e15a60.gif        private int priority;
img_a6339ee3e57d1d52bc7d02b338e15a60.gif
img_a6339ee3e57d1d52bc7d02b338e15a60.gif        /// 
<summary>
img_a6339ee3e57d1d52bc7d02b338e15a60.gif        /// 扩展类型
img_a6339ee3e57d1d52bc7d02b338e15a60.gif        /// 
</summary>
img_a6339ee3e57d1d52bc7d02b338e15a60.gif        public override Type ExtensionType
img_a6339ee3e57d1d52bc7d02b338e15a60.gif        {
img_a6339ee3e57d1d52bc7d02b338e15a60.gif            get { return typeof(TraceExtension); }
img_a6339ee3e57d1d52bc7d02b338e15a60.gif        }
img_a6339ee3e57d1d52bc7d02b338e15a60.gif        /// 
<summary>
img_a6339ee3e57d1d52bc7d02b338e15a60.gif        /// 优先级 
img_a6339ee3e57d1d52bc7d02b338e15a60.gif        /// 
</summary>
img_a6339ee3e57d1d52bc7d02b338e15a60.gif        public override int Priority
img_a6339ee3e57d1d52bc7d02b338e15a60.gif        {
img_a6339ee3e57d1d52bc7d02b338e15a60.gif            get { return priority; }
img_a6339ee3e57d1d52bc7d02b338e15a60.gif            set { priority = value; }
img_a6339ee3e57d1d52bc7d02b338e15a60.gif        }
img_a6339ee3e57d1d52bc7d02b338e15a60.gif        /// 
<summary>
img_a6339ee3e57d1d52bc7d02b338e15a60.gif        /// 用于记录该WebMethod的SoapMessage的文件的绝对路径
img_a6339ee3e57d1d52bc7d02b338e15a60.gif        /// 默认为c:\\log.txt;
img_a6339ee3e57d1d52bc7d02b338e15a60.gif        /// 
</summary>
img_a6339ee3e57d1d52bc7d02b338e15a60.gif        public string Filename
img_a6339ee3e57d1d52bc7d02b338e15a60.gif        {
img_a6339ee3e57d1d52bc7d02b338e15a60.gif            get
img_a6339ee3e57d1d52bc7d02b338e15a60.gif            {
img_a6339ee3e57d1d52bc7d02b338e15a60.gif                return filename;
img_a6339ee3e57d1d52bc7d02b338e15a60.gif            }
img_a6339ee3e57d1d52bc7d02b338e15a60.gif            set
img_a6339ee3e57d1d52bc7d02b338e15a60.gif            {
img_a6339ee3e57d1d52bc7d02b338e15a60.gif                filename = value;
img_a6339ee3e57d1d52bc7d02b338e15a60.gif            }
img_a6339ee3e57d1d52bc7d02b338e15a60.gif        }
img_a6339ee3e57d1d52bc7d02b338e15a60.gif    }   
img_a6339ee3e57d1d52bc7d02b338e15a60.gif}
img_a6339ee3e57d1d52bc7d02b338e15a60.gif
结下来,介绍一个如何使用该类:
如果要使让TraceExtension支持第一种记录方式,需要作的额外工作为:
只需要在要记录SoapMessage的WebMethod添加如下的Attribute
[TraceExtension(Filename="d:\\data.xml",Priority=0)]
当然路径,您可以自己设定
前一节的WebMethod就变成了
img_1c53668bcee393edac0d7b3b3daff1ae.gif img_405b18b4b6584ae338e0f6ecaf736533.gif 添加了针对WebMethod日志记录的WebMethod
img_a6339ee3e57d1d52bc7d02b338e15a60.gif public MySoapHeader header = new MySoapHeader();        
img_a6339ee3e57d1d52bc7d02b338e15a60.gif        [WebMethod]
img_a6339ee3e57d1d52bc7d02b338e15a60.gif        [SoapHeader("header")]   
img_a6339ee3e57d1d52bc7d02b338e15a60.gif        [TraceExtension(Filename="d:\\data.xml",Priority=0)]
img_a6339ee3e57d1d52bc7d02b338e15a60.gif        public string HelloWorld()
img_a6339ee3e57d1d52bc7d02b338e15a60.gif        {
img_a6339ee3e57d1d52bc7d02b338e15a60.gif            if (header == null)
img_a6339ee3e57d1d52bc7d02b338e15a60.gif            {
img_a6339ee3e57d1d52bc7d02b338e15a60.gif                return "您没有设置SoapHeader,不能正常访问此服务!";
img_a6339ee3e57d1d52bc7d02b338e15a60.gif            }
img_a6339ee3e57d1d52bc7d02b338e15a60.gif            if (header.UserName != "jillzhang" || header.Pwd != "123456")
img_a6339ee3e57d1d52bc7d02b338e15a60.gif            {
img_a6339ee3e57d1d52bc7d02b338e15a60.gif                return "您提供的身份验证信息有误,不能正常访问此服务!";
img_a6339ee3e57d1d52bc7d02b338e15a60.gif            }
img_a6339ee3e57d1d52bc7d02b338e15a60.gif            return "Hello World";
img_a6339ee3e57d1d52bc7d02b338e15a60.gif        }
调用下该WebService,便在d盘产生一个data.xml文件,里面的内容为:
img_1c53668bcee393edac0d7b3b3daff1ae.gif img_405b18b4b6584ae338e0f6ecaf736533.gif 日志记录
img_a6339ee3e57d1d52bc7d02b338e15a60.gif-----Soap请求 在 2007年05月25日 09时06分29秒
img_a6339ee3e57d1d52bc7d02b338e15a60.gif
<?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>
img_a6339ee3e57d1d52bc7d02b338e15a60.gif
img_a6339ee3e57d1d52bc7d02b338e15a60.gif
img_a6339ee3e57d1d52bc7d02b338e15a60.gif-----Soap响应 在 2007年05月25日 09时06分29秒
img_a6339ee3e57d1d52bc7d02b338e15a60.gif
<?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>
img_a6339ee3e57d1d52bc7d02b338e15a60.gif
如何采用第二种方法,让WebService的每个WebMethod都能记录日志
需要在Web.config中作如下的设定
首先添加如下节点
img_a6339ee3e57d1d52bc7d02b338e15a60.gif   < webServices >
img_a6339ee3e57d1d52bc7d02b338e15a60.gif        
< soapExtensionTypes >
img_a6339ee3e57d1d52bc7d02b338e15a60.gif          
< add  type ="Jillzhang.TraceExtension,Jillzhang"  priority ="1"   group ="High"    />
img_a6339ee3e57d1d52bc7d02b338e15a60.gif        
</ soapExtensionTypes >
img_a6339ee3e57d1d52bc7d02b338e15a60.gif      
</ webServices >
然后通过配置设定日志文件保留的路径:
img_a6339ee3e57d1d52bc7d02b338e15a60.gif < appSettings >
img_a6339ee3e57d1d52bc7d02b338e15a60.gif    
< add  key ="logRoot"  value ="d:" />
img_a6339ee3e57d1d52bc7d02b338e15a60.gif  
</ appSettings >
找到日志文件,里面也赫然有着SoapMessage的真面目。通过以上方法,大家可以清晰地分析到SoapMessage的具体格式和内容,知道了这个以后,对付Web Service,您就可以随心应手,随心所欲,如果你愿意,你甚至也可以“强奸"一次webservice,哈哈!
上一篇文章地址: 构建安全的Xml Web Service系列一之初探使用Soap头 (5-22 12:53)
附:终于买上房了,虽然买的过程很累,但现在还是很Happy!
相关实践学习
日志服务之使用Nginx模式采集日志
本文介绍如何通过日志服务控制台创建Nginx模式的Logtail配置快速采集Nginx日志并进行多维度分析。
目录
相关文章
|
11小时前
|
开发框架 中间件 数据库
Django 框架入门全攻略:轻松构建 Web 应用
【5月更文挑战第18天】本文是 Django 入门教程,介绍了如何使用 Django 构建 Web 应用。内容包括安装、项目与应用创建、模型定义、数据库迁移、视图编写、路由配置、模板系统、表单处理和中间件的使用。通过实例展示了 Django 基本流程,帮助初学者快速上手。Django 提供高效工具,便于开发者聚焦业务逻辑,轻松构建功能丰富的 Web 应用。
14 5
|
11小时前
|
数据库连接 Python
Flask 框架入门与实践:构建你的第一个 Web 应用
【5月更文挑战第18天】本文介绍了使用 Flask 框架构建第一个 Web 应用的步骤。首先通过 `pip install Flask` 安装框架,然后编写基本的 Python 代码创建应用,包括定义路由和响应。示例展示如何显示 &quot;Hello, World!&quot;,并扩展到显示用户信息的功能。利用模板(如 `index.html`)可使页面更丰富。随着学习深入,可以利用 Flask 的更多特性,如表单处理和数据库连接,来构建更复杂的 Web 应用。本文旨在激发读者对 Flask 和 Web 开发的兴趣,鼓励不断探索和实践。
14 7
|
1天前
|
缓存 监控 API
利用Python构建高性能的Web API后端服务
随着微服务架构的普及和RESTful API的广泛应用,构建高性能、可扩展的Web API后端服务变得尤为重要。本文将探讨如何利用Python这一强大且灵活的语言,结合现代Web框架和工具,构建高效、可靠的Web API后端服务。我们将分析Python在Web开发中的优势,介绍常用的Web框架,并通过实际案例展示如何设计并实现高性能的API服务。
|
1天前
|
前端开发 Java Go
从前端到后端:构建现代化Web应用的技术实践
本文将介绍如何通过前端和后端技术相结合,构建现代化Web应用的技术实践。我们将探讨前端开发、后端架构以及多种编程语言(如Java、Python、C、PHP、Go)在构建高效、可扩展的Web应用中的应用。
|
2天前
|
JavaScript 前端开发 API
Vue中的组件:构建现代Web应用的基石
Vue中的组件:构建现代Web应用的基石
|
2天前
|
前端开发 JavaScript 开发者
深入理解MVC和MVVM:构建现代Web应用的利器
深入理解MVC和MVVM:构建现代Web应用的利器
|
2天前
|
应用服务中间件 网络安全 Apache
构建高性能Web服务器:Nginx vs Apache
【5月更文挑战第16天】Nginx与Apache是两种主流Web服务器,各具优势。Nginx以其轻量级、高并发处理能力和反向代理功能见长,适合大型网站和高并发场景;而Apache以功能丰富、稳定性强闻名,适合企业网站和需要多种Web服务功能的场景。在性能上,Nginx处理高并发更优,Apache则可能在高负载时遭遇瓶颈。在选择时,应根据实际需求权衡。
|
3天前
|
Android开发
android string.xml文件中的整型和string型代替
android string.xml文件中的整型和string型代替
|
3天前
|
XML 前端开发 数据格式
BeautifulSoup 是一个 Python 库,用于从 HTML 和 XML 文件中提取数据
【5月更文挑战第10天】BeautifulSoup 是 Python 的一个库,用于解析 HTML 和 XML 文件,即使在格式不规范的情况下也能有效工作。通过创建 BeautifulSoup 对象并使用方法如 find_all 和 get,可以方便地提取和查找文档中的信息。以下是一段示例代码,展示如何安装库、解析 HTML 数据以及打印段落、链接和特定类名的元素。BeautifulSoup 还支持更复杂的查询和文档修改功能。
22 1
|
3天前
|
XML 安全 API
AndroidManifest.xml文件综合详解
AndroidManifest.xml文件综合详解
10 2