在SOAP请求中使用自定义字段实现WSSE安全标头时,C#运行时错误 [英] C# Runtime Error when implementing WSSE Security Headers with custom fields in SOAP request

查看:66
本文介绍了在SOAP请求中使用自定义字段实现WSSE安全标头时,C#运行时错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试向使用 WSSE 和UsernameToken进行身份验证的Web服务发送 SOAP请求.示例查询如下(掩盖机密数据):

I am trying to send a SOAP request to a web service that uses WSSE and UsernameToken for authentication. The sample query is as follows (masking confidential data):

<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 生成了一个代理类,问题是我得到了错误:对象引用未设置为对象的实例."我的C#代码中有问题的部分如下:

I have generated a proxy class using WSE 3.0 and the problem is that I get the error: "Object reference not set to an instance of an object." The problematic part of my C# code is below:

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;

我通过系统地注释掉我的代码部分来定位有问题的部分.我对Web服务非常陌生,C#实际上是在 Blue Prism 中实现的.尽管此程序可以立即使用SOAP Web服务,但是不幸的是,它本身并不支持SOAP标头.

I located the problematic part by systemically commenting out portions of my code. I am quite unfamiliar with web services, C# and I am actually implementing this in Blue Prism. Although this program works with SOAP web services out of the box, unfortunately it does not natively support SOAP headers.

SOAP请求在 SOAP UI 中正常工作,并且Blue Prism中没有编译器错误.我尝试按照手册和网络上的说明添加标题,但没有用.如果您能指出正确的方向,我将不胜感激.

The SOAP request works fine in SOAP UI and there are no compiler errors in Blue Prism. I tried adding the headers as instructed in the manual and on the web, but it did not work. I would appreciate it if you could point me in the right direction.

编辑编写后,在Visual Studio 2017中编译控制台应用程序,我得到以下错误.据我了解,它没有标题的定义.

EDIT After writing, compiling a console application in Visual Studio 2017 I get the following error. As far as I understand it does not have the definitions for the headers.

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

推荐答案

我决定使用其他方法,由于存在相关问题,因此暂时不尝试使用代理类.利用此链接上的答案:客户端发送SOAP请求并接收响应经过一些自定义后,我想出了自己的解决方案.

I decided to utilize a different method and quit trying to use a proxy class for the time being as there were problems associated with it. Making use of the answers on this link: Client to send SOAP request and receive response I came up with my own solution after some customization.

但是,我仍然想知道如何继续使用Visual Studio或WSE 3.0定义的包装器类使它正常工作.在编写代码并在Visual Studio中对其进行测试之后,将其移植到Blue Prism中非常容易.

However, I still wonder how to proceed in order to make it work using wrapper classes defined by Visual Studio or WSE 3.0. After writing the code and testing it in Visual Studio it was pretty easy to port it into 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!!!";
            }
        }
    }
}

这篇关于在SOAP请求中使用自定义字段实现WSSE安全标头时,C#运行时错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆