Получать (и отправлять) XML через POST с ASP.NET - PullRequest
4 голосов
/ 12 мая 2010

Мне нужно настроить «веб-сервис» XML, который получает POST, где в заголовке типа контента будет указано «text / xml».

Какой самый простой способ вставить XML в XDocument для доступа по запросам оси VB.NET?

Я не верю, что веб-сервис гарантированно будет следовать любому протоколу (например, SOAP и т. Д.); только определенные теги и под-теги для различных запросов, и он будет использовать базовую аутентификацию, поэтому мне придется обрабатывать заголовки.

(Если это имеет значение:
* живая версия будет использовать HTTPS, а
* ответ также будет XML.)

Ответы [ 3 ]

8 голосов
/ 12 мая 2010

С учетом предупреждения Стивена, ответ может состоять в том, чтобы вручную проанализировать Request.InputStream, сначала тест Тома Холланда , а затем XDocument.Load в событии Page_Load.

Поиск в Google начался до того, как я задал вопрос, но проверил только после того, как нашел этот , что также указывает на то, что я на правильном пути.

Кроме того, я собирался задать вопрос, подразумеваемый моей точкой зрения, что ответом должен быть и XML, что является лучшим способом для этого, но я нашел ответ здесь .

В итоге, окончательный код:

 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 Throwing HTTPException не является окончательным решением для нежелательных сценариев.

3 голосов
/ 12 мая 2010

Я хочу заранее извиниться за то, что не ответил на ваш вопрос здесь, но я хочу дать небольшое предупреждение. Возможно, это уже то, что вы принимаете во внимание, но если вы не примете соответствующие контрмеры, ваша система может быть легко отключена с помощью атаки типа «отказ в обслуживании» при обработке 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>

Этот небольшой XML-документ размером менее 500 байт заставит ваш сервер попытаться выделить как минимум 160 ГБ памяти.

Вы можете защитить себя от этого, проверяя входящий XML (с DTD) перед его обработкой.

Вы можете прочитать больше информации об этой атаке, здесь .

Удачи.

0 голосов
/ 12 мая 2010

Когда вы создаете веб-службу , вы определяете формат XML-файла, который вы получите, и отправитель должен соответствовать вашему формату.

Я обычно копирую информацию, которую мой веб-сервис получит как DataTables в DataSet (так как это близко имитирует, как я могу сохранить их в базе данных), затем выполняю DataSet.getXML() для моего макета DataSet (возможно, также получая схему по умолчанию) для использования в качестве шаблона для XML, который я ожидаю "опубликовать" в моем веб-сервисе.

Затем, когда мой веб-сервис получает сообщение, я могу просто взять отправленный XML и использовать DataSet.readXML() в опубликованном XML ... и обработать информацию, отправленную в DataSet.

Большинство значений "возврата" моего веб-сервиса являются результатами запросов, основанных на опубликованной информации, поэтому я делаю то же самое для форматирования возвращаемых значений ... получаю результаты моих запрашиваемых данных возврата в DataSet, DataSet.getXML() .. и верните его.

...