国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁(yè) > 開(kāi)發(fā) > XML > 正文

構(gòu)建安全的Xml Web Service系列(二)

2024-09-05 20:55:58
字體:
來(lái)源:轉(zhuǎn)載
供稿:網(wǎng)友

  上一篇文章地址:構(gòu)建安全的xml web service系列一之初探使用soap頭

  要分析xml web service的安全性,首先要解決的問(wèn)題是我們能了解和清楚soap消息的格式和內(nèi)容,如果獲得不了soapmessage,分析如何能構(gòu)建安全xml web service也就無(wú)從下手,即使分析出來(lái),自己也可能模模糊糊,不能定論。下面就分析下如何獲得soapmessage。

  首先介紹一個(gè)類(lèi)-soapextension,msdn對(duì)這個(gè)類(lèi)的備注為:asp.net 允許通過(guò)擴(kuò)展性機(jī)制生成與 soap 相關(guān)的基礎(chǔ)結(jié)構(gòu)。asp.net soap 擴(kuò)展結(jié)構(gòu)以一種擴(kuò)展為中心,該擴(kuò)展可以在客戶(hù)端或服務(wù)器上處理消息時(shí)在特定階段中檢查或修改消息。asp.net soap 擴(kuò)展從 soapextension 類(lèi)派生。getinitializer 和 initialize 方法提供其他可用機(jī)制,用于初始化 soap 擴(kuò)展以增強(qiáng)性能。processmessage 是大多數(shù) soap 擴(kuò)展的核心,原因是該方法在 soapmessagestage 中定義的每一個(gè)階段都被調(diào)用,從而使 soap 擴(kuò)展得以執(zhí)行所需的該特定 soap 擴(kuò)展的行為。對(duì)于需要修改 soap 請(qǐng)求或 soap 響應(yīng)的 soap 擴(kuò)展,chainstream 提供一個(gè)機(jī)會(huì)以接收要通過(guò)網(wǎng)絡(luò)發(fā)送的建議數(shù)據(jù)。 仔細(xì)閱讀這段文字,如果您以前開(kāi)發(fā)過(guò)windows程序,那第一個(gè)應(yīng)該想到的是:原來(lái)web service的處理機(jī)制和windows窗口程序的消息機(jī)制竟然有著一曲同工之妙。下面談?wù)勅绾卫眠@個(gè)類(lèi),來(lái)截獲xml web service請(qǐng)求和相應(yīng)的soap消息,從而看看xml web service的廬山真面目。

  首先大家先看看這個(gè)類(lèi),這個(gè)類(lèi)完成的功能是將xml web service通過(guò)擴(kuò)展的方式,將每次的請(qǐng)求和響應(yīng)的soap消息通過(guò)日志的方式保存到文本文件中。日志記錄的方式也有兩種:

  1。針對(duì)每個(gè)webmethod產(chǎn)生一個(gè)日志文件。

  2。針對(duì)每個(gè)webservice產(chǎn)生一個(gè)日志文件

  因?yàn)橐粋€(gè)webservice可能包含一個(gè)或者多個(gè)webmethod,所以如果指定兩種方法都支持的話,那第二個(gè)日志兩面應(yīng)該包括第一個(gè)日志里面的內(nèi)容,而有些情況下,是不需要對(duì)每個(gè)webmethod都進(jìn)行日志記錄的,這時(shí)候采用第一種記錄方式,增強(qiáng)了系統(tǒng)的靈活性。

  下面是擴(kuò)展了的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>
       /// 將請(qǐng)求流和響應(yīng)流存到內(nèi)存流中,已被調(diào)用
       /// </summary>
        /// <param name="stream">包含 soap 請(qǐng)求或響應(yīng)的內(nèi)存緩沖區(qū)</param>
        /// <returns>它表示此 soap 擴(kuò)展可以修改的新內(nèi)存緩沖區(qū)。</returns>
        public override stream chainstream(stream stream)
        {
            oldstream = stream;
            newstream = new memorystream();
            return newstream;
        }
        /// <summary>
        /// 在xml web service第一次運(yùn)行的時(shí)候,一次性的將通過(guò)traceextensionattribute傳遞進(jìn)來(lái)的
        /// 保存日志信息的文件名初始化
        /// </summary>
        /// <param name="methodinfo">應(yīng)用 soap 擴(kuò)展的 xml web services 方法的特定函數(shù)原型</param>
        /// <param name="attribute">應(yīng)用于 xml web services 方法的 soapextensionattribute</param>
        /// <returns>soap 擴(kuò)展將對(duì)其進(jìn)行初始化以用于緩存</returns>
        public override object getinitializer(logicalmethodinfo methodinfo, soapextensionattribute attribute)
        {
            return ((traceextensionattribute)attribute).filename;
        }
        /// <summary>
        /// 替代為每個(gè)方法配置的保存soapmessage文件名,而是將整個(gè)網(wǎng)絡(luò)服務(wù)
        /// 的soapmessage都保存到一個(gè)日志文件中,這個(gè)文件路徑需要在web service
        /// 的配置文件中web.config指出,如
        /// <appsettings>
        ///  <add key="logroot" value="c://servicelog"/>
        /// </appsettings>
        /// </summary>
        /// <param name="webservicetype">網(wǎng)絡(luò)服務(wù)的類(lèi)型</param>
        /// <returns>用于保存日志記錄的文件路徑</returns>
        public override object getinitializer(type webservicetype)
        {
            //return logroot.trimend('//') + "http://" + webservicetype.fullname + ".log";
            return logroot.trimend('//')+"http://"+ webservicetype.fullname + ".log";
        }
        //獲得文件名,并將其保存下來(lái)
        public override void initialize(object initializer)
        {
            filename = (string)initializer;
        }
       /// <summary>
       /// 當(dāng)數(shù)據(jù)還為soap格式的時(shí)候,將數(shù)據(jù)寫(xiě)入日志
       /// </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寫(xiě)入到日志文件
        /// </summary>
        /// <param name="message"></param>
        public void writeoutput(soapmessage message)
        {
            newstream.position = 0;
            //創(chuàng)建或追加記錄文件
            filestream fs = new filestream(filename, filemode.append,
                fileaccess.write);
            streamwriter w = new streamwriter(fs);
            string soapstring = (message is soapservermessage) ? "soap響應(yīng)" : "soap請(qǐng)求";
            w.writeline("-----" + soapstring + " 在 " + datetime.now.tostring("yyyy年mm月dd日 hh時(shí)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請(qǐng)求" : "soap響應(yīng)";
            w.writeline("-----" + soapstring +
                " 在 " + datetime.now.tostring("yyyy年mm月dd日 hh時(shí)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();
        }
    }
    //創(chuàng)建一個(gè)用于在webmethod上使用的soapextension屬性
    [attributeusage(attributetargets.method)]
    public class traceextensionattribute : soapextensionattribute
    {
        private string filename = "c://log.txt";
        private int priority;
        /// <summary>
        /// 擴(kuò)展類(lèi)型
        /// </summary>
        public override type extensiontype
        {
            get { return typeof(traceextension); }
        }
        /// <summary>
        /// 優(yōu)先級(jí)
        /// </summary>
        public override int priority
        {
            get { return priority; }
            set { priority = value; }
        }
        /// <summary>
        /// 用于記錄該webmethod的soapmessage的文件的絕對(duì)路徑
        /// 默認(rèn)為c://log.txt;
        /// </summary>
        public string filename
        {
            get
            {
                return filename;
            }
            set
            {
                filename = value;
            }
        }
    }  
}

  結(jié)下來(lái),介紹一個(gè)如何使用該類(lèi):

  如果要使讓traceextension支持第一種記錄方式,需要作的額外工作為:

  只需要在要記錄soapmessage的webmethod添加如下的attribute

  [traceextension(filename="d://data.xml",priority=0)]

  當(dāng)然路徑,您可以自己設(shè)定

  前一節(jié)的webmethod就變成了

添加了針對(duì)webmethod日志記錄的webmethod
public mysoapheader header = new mysoapheader();       
        [webmethod]
        [soapheader("header")]  
        [traceextension(filename="d://data.xml",priority=0)]
        public string helloworld()
        {
            if (header == null)
            {
                return "您沒(méi)有設(shè)置soapheader,不能正常訪問(wèn)此服務(wù)!";
            }
            if (header.username != "jillzhang" || header.pwd != "123456")
            {
                return "您提供的身份驗(yàn)證信息有誤,不能正常訪問(wèn)此服務(wù)!";
            }
            return "hello world";
        }
 
  調(diào)用下該webservice,便在d盤(pán)產(chǎn)生一個(gè)data.xml文件,里面的內(nèi)容為:

-----soap請(qǐng)求 在 2007年05月25日 09時(shí)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="jillzhang123456http://tempuri.org/"><username>jillzhang</username><pwd>123456</pwd></mysoapheader></soap:header><soap:body><helloworld xmlns="http://tempuri.org/" /></soap:body></soap:envelope>
 
 
 
-----soap響應(yīng) 在 2007年05月25日 09時(shí)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="hello'>http://tempuri.org/"><helloworldresult>hello world</helloworldresult></helloworldresponse></soap:body></soap:envelope>

  如何采用第二種方法,讓webservice的每個(gè)webmethod都能記錄日志

  需要在web.config中作如下的設(shè)定

  首先添加如下節(jié)點(diǎn)

<webservices>
        <soapextensiontypes>
          <add type="jillzhang.traceextension,jillzhang" priority="1"  group="high"  />
        </soapextensiontypes>
      </webservices>

  然后通過(guò)配置設(shè)定日志文件保留的路徑:

<appsettings>
    <add key="logroot" value="d:"/>
  </appsettings>

  找到日志文件,里面也赫然有著soapmessage的真面目。通過(guò)以上方法,大家可以清晰地分析到soapmessage的具體格式和內(nèi)容,知道了這個(gè)以后,對(duì)付web service,您就可以隨心應(yīng)手,隨心所欲,如果你愿意,你甚至也可以“強(qiáng)奸"一次webservice,哈哈!


發(fā)表評(píng)論 共有條評(píng)論
用戶(hù)名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 青州市| 赤水市| 白城市| 汉阴县| 饶河县| 维西| 平和县| 阿拉善左旗| 黑水县| 城口县| 寿光市| 获嘉县| 时尚| 奉新县| 蒲江县| 武穴市| 于田县| 阿克| 大丰市| 梅河口市| 万源市| 沈阳市| 阿巴嘎旗| 黔西| 华坪县| 江阴市| 紫阳县| 黄石市| 陆川县| 贡山| 顺义区| 昔阳县| 保靖县| 文山县| 怀化市| 汕尾市| 连云港市| 敦化市| 思南县| 时尚| 襄汾县|