Ошибка выполнения C# при реализации заголовков безопасности WSSE с настраиваемыми полями в запросе SOAP

Я пытаюсь отправить запрос SOAP веб-службе, которая использует для аутентификации WSSE и UsernameToken. Пример запроса выглядит следующим образом (маскирование конфиденциальных данных):

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:kas="http://webservice.com">
        <soapenv:Header>
      <wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
         <wsse:UsernameToken>
            <wsse:Username>abc</wsse:Username>
            <wsse:CustomField>123</wsse:CustomField>
         </wsse:UsernameToken>
      </wsse:Security>
   </soapenv:Header>
   <soapenv:Body>
      <kas:method1>
         <!--Optional:-->
         <method1>
            <!--Optional:-->
            <queryNo>12345678901</queryNo>
         </method1>
      </kas:method1>
   </soapenv:Body>
</soapenv:Envelope> 

Я создал прокси-класс, используя WSE 3.0, и проблема в том, что я получаю сообщение об ошибке: "Ссылка на объект не указывает на экземпляр объекта". Проблемная часть моего кода С# приведена ниже:

queryNoSorguType q = new queryNoSorguType();
string query_parameter = query_no;
q.queryNo = query_parameter;

ResultType[] r = new ResultType[10];

UsernameToken token = new UsernameToken("abc", "123",PasswordOption.SendPlainText);
//mWebService.SetClientCredential<UsernameToken>(token);
//Policy webServiceClientPolicy = new Policy();
mWebService.RequestSoapContext.Security.Tokens.Add(token);
//mWebService.SetPolicy(webServiceClientPolicy);

//r = mWebService.documentQuerybyQueryNo(q);

System.Data.DataTable outputDataTable = new System.Data.DataTable();
//System.Data.DataRow outRow = outputDataTable.Rows.Add();
//outRow["field1"] = r;
output = outputDataTable;

Я нашел проблемную часть, систематически комментируя части своего кода. Я совершенно не знаком с веб-сервисами, C# и фактически реализую это в Blue Prism. Хотя эта программа работает с веб-службами SOAP из коробки, к сожалению, она изначально не поддерживает заголовки SOAP.

Запрос SOAP отлично работает в SOAP UI, и в Blue Prism нет ошибок компиляции. Я попытался добавить заголовки, как указано в руководстве и в Интернете, но это не сработало. Я был бы признателен, если бы вы могли указать мне в правильном направлении.

EDIT После написания компиляции консольного приложения в Visual Studio 2017 я получаю следующую ошибку. Насколько я понимаю, у него нет определений для заголовков.

Unhandled Exception: System.Web.Services.Protocols.SoapHeaderException: MustUnderstand headers:[{http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd}Security] are not understood
   at System.Web.Services.Protocols.SoapHttpClientProtocol.ReadResponse(SoapClientMessage message, WebResponse response, Stream responseStream, Boolean asyncCall)
   at System.Web.Services.Protocols.SoapHttpClientProtocol.Invoke(String methodName, Object[] parameters)
   at WebService.queryByQueryNo(queryNoQueryType queryByQueryNo1) in C:\Users\user\source\repos\ConsoleApp1\ConsoleApp1\Web References\WebService\Reference.cs:line 1533
   at ConsoleApp1.Program.Main(String[] args) in C:\Users\user\source\repos\ConsoleApp1\ConsoleApp1\Program.cs:line 33

person Vesnog    schedule 19.05.2018    source источник
comment
если вы отлаживаете, я предлагаю проверить каждую часть mWebService.RequestSoapContext.Security.Tokens, если mWebService.RequestSoapContext или mWebService.RequestSoapContext.Security или mWebService.RequestSoapContext.Security.Tokens имеет значение null, ваш код не будет работать.   -  person ralf.w.    schedule 25.05.2018
comment
@ralf.w. Спасибо за комментарий. На самом деле после изоляции программы и запуска ее через Visual Studio я получаю разные ошибки. Пожалуйста, смотрите отредактированный вопрос выше.   -  person Vesnog    schedule 26.05.2018
comment
@Vesnog, вы упомянули, что запрос SoapUI работает нормально. Не могли бы вы предоставить дампы запросов мыла из SoapUI и из вашего приложения .net?   -  person n.prokhorov    schedule 29.05.2018
comment
@Vesnog и соответствующие ответы сервера   -  person n.prokhorov    schedule 29.05.2018
comment
у вас есть какой-либо сертификат безопасности, участвующий в этом процессе?   -  person Pavan    schedule 30.05.2018
comment
@Vesnog, ты не мог бы увидеть мой ответ?   -  person Emiliano    schedule 01.06.2018
comment
@Pavan Нет, у меня нет сертификата, участвующего в этом процессе.   -  person Vesnog    schedule 02.06.2018


Ответы (2)


Я думаю, что структура xml пунктуально заголовки, когда вы используете

<wsse:Security wsse не определен, я знаю, что вы определили в той же строке, но почему бы не попробовать поместить его в документ, что-то вроде этого

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:kas="http://webservice.com" xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
   <soapenv:Header>
      <wsse:Security>
         <wsse:UsernameToken>
            <wsse:Username>abc</wsse:Username>
            <wsse:CustomField>123</wsse:CustomField>
         </wsse:UsernameToken>
      </wsse:Security>
   </soapenv:Header>
person Emiliano    schedule 30.05.2018
comment
@Vesnog Не могли бы вы увидеть мой ответ? - person Emiliano; 01.06.2018
comment
Здравствуйте, спасибо за ответ, проблема в том, что я пытался отправить запрос SOAP, используя классы-оболочки, созданные Visual Studio. Я не совсем понял вашу мысль. - person Vesnog; 02.06.2018

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

Однако мне все еще интересно, как действовать, чтобы заставить его работать с использованием классов-оболочек, определенных Visual Studio или WSE 3.0. После написания кода и его тестирования в Visual Studio было довольно легко перенести его в Blue Prism.

using System;
using System.Collections.Generic;
using System.Data;
using System.Text;
using System.Threading.Tasks;
using System.Xml;
using System.Net;
using System.IO;
using System.Xml.Linq;
namespace WebService
{
    class Program
    {
        /// <summary>
        /// Execute a Soap WebService call
        /// </summary>
        public static string Execute(string queryNo)
        {
            HttpWebRequest request = CreateWebRequest();
            XmlDocument soapEnvelopeXml = new XmlDocument();
            soapEnvelopeXml.LoadXml(@"<?xml version=""1.0"" encoding=""utf-8""?>
                <soapenv:Envelope xmlns:soapenv=""http://schemas.xmlsoap.org/soap/envelope/"" xmlns:customNAMESPACE=""http://webservice.com"">
                <soapenv:Header>
                    <wsse:Security xmlns:wsse=""http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"">
                        <wsse:UsernameToken>
                            <wsse:Username>USER</wsse:Username>
                            <wsse:CustomField>CODE</wsse:CustomField>
                        </wsse:UsernameToken>
                     </wsse:Security>
                  </soapenv:Header>
                  <soapenv:Body>
                     <customNAMESPACE:QueryByQueryNo>
                        <!--Optional:-->
                        <QueryByQueryNo>
                            <!--Optional:-->
                            <queryNo>" + queryNo + @"</queryNo>
                        </QueryByQueryNo>
                      </customNAMESPACE:QueryByQueryNo>
                  </soapenv:Body>
                </soapenv:Envelope>");

            using (Stream stream = request.GetRequestStream())
            {
                soapEnvelopeXml.Save(stream);
            }

            using (WebResponse response = request.GetResponse())
            {
                using (StreamReader rd = new StreamReader(response.GetResponseStream()))
                {
                    string soapResult = rd.ReadToEnd();
                    Console.WriteLine(soapResult);
                    return soapResult;
                }
            }
        }
        /// <summary>
        /// Create a soap webrequest to [Url]
        /// </summary>
        /// <returns></returns>
        public static HttpWebRequest CreateWebRequest()
        {
            HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(@"https://webservice.com/webservice?wsdl");
            webRequest.Headers.Add(@"SOAP:Action");
            webRequest.ContentType = "text/xml;charset=\"utf-8\"";
            webRequest.Accept = "text/xml";
            webRequest.Method = "POST";
            return webRequest;
        }
        static void Main(string[] args)
        {
            if (args.Length == 0 || args.Length > 1)
            {
                System.Console.WriteLine("Please provide a query no");
                System.Console.WriteLine("Usage: WebService.exe 3523423333");
                return;
            }

            string output, XMLresponse;
            try
            {
                XMLresponse = Execute(args[0]);
                output = "Successful query";
                XmlDocument xml = new XmlDocument();
                xml.LoadXml(XMLresponse);  // suppose that str string contains the XML data. You may load XML data from a file too.
                XmlNodeList resultCodeList = xml.GetElementsByTagName("resultCode");
                XmlNodeList resultNoList = xml.GetElementsByTagName("resultNo");
                int i = 0;
                var OutputTable = new DataTable();
                OutputTable.Columns.Add("Result Code", typeof(string));
                OutputTable.Columns.Add("Result No", typeof(string));
                foreach (XmlNode xn in resultCodeList)
                {
                    Console.WriteLine(resultCodeList[i].InnerText + "  " + resultNoList[i].InnerText);
                    OutputTable.Rows.Add(resultCodeList[i].InnerText, resultNoList[i].InnerText);
                    i++;
                }

            }
            catch (System.Net.WebException exc)
            {
                Console.WriteLine("HTTP POST request failed!");
                output = "!!!HTTP POST request failed!!!";
            }
        }
    }
}
person Vesnog    schedule 03.06.2018