使用ASP.NET通过POST接收(和发送)XML

时间:2010-05-12 04:59:00

标签: asp.net .net xml web-services .net-3.5

我必须设置一个XML“Web服务”,它接收一个POST,其中'Content-type标题将指定“text / xml”。'

将XML转换为XDocument以便VB.NET轴查询访问的最简单方法是什么?

我不相信Web服务可以保证遵循任何协议(例如SOAP等);只是针对各种请求的特定标签和子标签,它将使用基本身份验证,因此我将不得不处理标头。

(如果重要:
 *实时版本将使用HTTPS和
 *响应也将是XML。)

3 个答案:

答案 0 :(得分:8)

鉴于史蒂文的警告,答案可能是首先用Tom Holland's test手动解析Request.InputStream,然后在XDocument.Load事件中手动解析Page_Load

在我提出问题之前启动了Google搜索,但只检查过后,发现this,也表明我已走上正轨。

此外,我还要问一下我的观点暗示的问题,即响应必须是XML,关于最佳方法是什么,但我找到了答案here

总之,最终的代码是:

 Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load

    If Request.ContentType <> "text/xml" Then _
        Throw New HttpException(500, "Unexpected Content-Type")

    Dim id = CheckBasicAuthentication

    Dim textReader = New IO.StreamReader(Request.InputStream)

    CheckXmlValidity(textReader)

    ' Reset the stream & reader
    Request.InputStream.Seek(0, IO.SeekOrigin.Begin)
    textReader.DiscardBufferedData()

    Dim xmlIn = XDocument.Load(textReader)

    ' process XML in xmlIn

    Dim xmlOut = <?xml version="1.0" encoding="UTF-8" ?>
                 <someresult>
                     <header>
                         <id><%= id.ToString() %></id>
                         <datestamp>To be inserted</datestamp>
                     </header>
                     <result/>
                 </someresult>

    ' Further generation of XML for output

    xmlOut.<someresult>.<header>.<datestamp>.Value = Date.UtcNow.ToString(xmlDateFormat)
    xmlText.Text = xmlOut.ToString
End Sub

Private Function CheckBasicAuthentication() As Integer
    Dim httpAuthorisation = Request.Headers("Authorization")
    If Left(httpAuthorisation, 6).ToUpperInvariant <> "BASIC " Then _
        Throw New HttpException(401, "Basic Authentication Required")
    Dim authorization = Convert.FromBase64String(Mid(httpAuthorisation, 7))
    Dim credentials = Text.Encoding.UTF8.GetString(authorization).Split(":"c)
    Dim username = credentials(0)
    Dim password = credentials(1)

    Return ConfirmValidUser(username, password)
End Function

Private Shared Sub CheckXmlValidity(ByVal textReader As System.IO.StreamReader)
    Try
        ' Check for "interesting" xml documents.
        Dim settings = New System.Xml.XmlReaderSettings()
        settings.XmlResolver = Nothing
        settings.MaxCharactersInDocument = 655360
        ' Successfully parse the file, otherwise an XmlException is to be thrown. '
        Dim reader = System.Xml.XmlReader.Create(textReader, settings)
        Try
            While reader.Read()
                'Just checking.
            End While
        Finally
            reader.Close()
        End Try
    Catch ex As Exception
        Throw New HttpException(500, "Invalid Xml data", ex)
    End Try
End Sub

和ASP.NET webpage.aspx是:

<%@ Page Language="VB" AutoEventWireup="false" CodeFile="webpage.aspx.vb" Inherits="WebPage" ContentType="text/xml" %>

<asp:Literal ID="xmlText" runat="server" Mode="PassThrough"></asp:Literal> 

NB投掷HTTPException不是有害情况的有效最终解决方案。

答案 1 :(得分:3)

我想提前道歉,因为这里没有回答你的问题,但我想发一点警告。也许它已经是你正在考虑的事情,但是如果你没有采取适当的对策,当处理来自未知来源的XML(通过HTTP和HTTP)时,可以使用拒绝服务攻击轻松关闭系统。 HTTPS)。

有一种称为XML实体扩展攻击的技术。例如,看看这种无辜的XML平衡,当它试图处理它时会让你的服务器瘫痪:

<!DOCTYPE foo [ 
<!ENTITY a "1234567890" > 
<!ENTITY b "&a;&a;&a;&a;&a;&a;&a;&a;" > 
<!ENTITY c "&b;&b;&b;&b;&b;&b;&b;&b;" > 
<!ENTITY d "&c;&c;&c;&c;&c;&c;&c;&c;" > 
<!ENTITY e "&d;&d;&d;&d;&d;&d;&d;&d;" > 
<!ENTITY f "&e;&e;&e;&e;&e;&e;&e;&e;" > 
<!ENTITY g "&f;&f;&f;&f;&f;&f;&f;&f;" > 
<!ENTITY h "&g;&g;&g;&g;&g;&g;&g;&g;" > 
<!ENTITY i "&h;&h;&h;&h;&h;&h;&h;&h;" > 
<!ENTITY j "&i;&i;&i;&i;&i;&i;&i;&i;" > 
<!ENTITY l "&k;&k;&k;&k;&k;&k;&k;&k;" > 
<!ENTITY m "&l;&l;&l;&l;&l;&l;&l;&l;" > 
]> 
<foo>&m;</foo>

这个少于500字节的小XML文档将使您的服务器尝试分配至少160 GB的内存。

您可以在处理传入的XML(使用DTD)之前保护自己免受此攻击。

您可以阅读有关此次攻击的更多信息here

祝你好运。

答案 2 :(得分:0)

创建Web服务时,定义您将收到的XML格式,并由发件人决定是否符合您的格式。

我通常会在DataTables中模拟我的网络服务将收到DataSet的信息(因为这非常类似于我可能将它们存储在数据库中),然后执行DataSet.getXML()我的模拟DataSet(也可能也是默认模式)用作我希望“发布”到我的Web服务的XML模板。

然后,当我的Web服务收到帖子时,我可以简单地获取发送的XML并使用发布的XML上的DataSet.readXML() ...并处理DataSet中发送的信息。 / p>

我的大多数网络服务“返回”值都是基于发布信息的查询结果,所以我也会这样做来格式化返回值...在{{1}中获取我的返回查询数据的结果},DataSet ..并将其归还。