代码之家  ›  专栏  ›  技术社区  ›  Mark Hurd

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

  •  4
  • Mark Hurd  · 技术社区  · 14 年前

    我必须设置一个XML“Web服务”,它接收一个帖子,其中“content-type header”将指定__text/xml_。

    将XML转换为 XDocument 用于通过vb.net的轴查询进行访问?

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

    (如果有关系的话:
    *实时版本将使用HTTPS,并且
    *响应也将是XML。)

    3 回复  |  直到 14 年前
        1
  •  8
  •   Mark Hurd    12 年前

    鉴于史蒂文的警告,答案可能是 Request.InputStream 手动与 Tom Holland's test 先,后 XDocument.Load Page_Load 事件。

    在我问这个问题之前启动了一个谷歌搜索,但只在之后检查,发现 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网页.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 对于不需要的方案不是有效的最终解决方案。

        2
  •  3
  •   Steven    11 年前

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

    有一种称为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之前,您可以通过验证传入的XML(使用DTD)来防止这种情况发生。

    你可以阅读更多关于这次攻击的信息, here .

    祝你好运。

        3
  •  0
  •   Mark Hurd    12 年前

    创建Web服务时 定义您将接收的XML的格式,由发送者来满足您的格式。

    我通常模拟我的Web服务将收到的信息 DataTables 在一个 DataSet (因为这很接近于我如何将它们存储在数据库中)然后 DataSet.getXML() 在我的嘲弄中 数据集 (也可能获得默认模式)用作XML的模板,我希望它“发布”到我的Web服务。

    然后,当我的Web服务收到一个帖子时,我可以简单地接收发送的XML并使用 DataSet.readXML() 在发布的XML上…处理发送的信息 数据集 .

    我的大部分Web服务“返回”值都是基于发布的信息进行查询的结果,因此我也会对返回值进行同样的格式化…获取返回查询数据的结果 数据集 , dataset.getxml()。 …然后把它还给我。