【问题标题】:How can I add a SOAP authentication header with HTTPRequestMessage?如何使用 HTTPRequestMessage 添加 SOAP 身份验证标头?
【发布时间】:2017-07-14 13:03:32
【问题描述】:

这是标题的样子

<soap:Header>
   <AuthenticationHeader>
     <UserName>string</UserName>
     <Password>string</Password>
   </AuthenticationHeader>
 </soap:Header>

这是我尝试过的:

string username = "TheUserName";
string password = "ThePassword";

HttpRequestMessage requestMessage = new HttpRequestMessage(method, uri);
requestMessage.Headers.Add("UserName", username);
requestMessage.Headers.Add("Password", password);

也许我必须以某种方式设置授权标头?

requestMessage.Headers.Authorization = ??

我觉得我必须以某种方式“构建”AuthenticationHeader 元素,但我不知道该怎么做。有什么建议吗?

编辑:完整的 SOAP 信封

?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
  <soap:Header>
    <AuthenticationHeader xmlns="http://www.test.com/testing/Security">
      <UserName>string</UserName>
      <Password>string</Password>
    </AuthenticationHeader>
  </soap:Header>
  <soap:Body>
    <GetMeSomething xmlns="http://www.test.com/testing/WorkFileCatalog">
      <Param1>string</Param1>
      <Param2>string</Param2>
      <XMLRetMess>string</XMLRetMess>
    </GetMeSomething>
  </soap:Body>
</soap:Envelope>

【问题讨论】:

  • 正常和通用的方法是将用户和密码附加到用于发送请求的对象上,例如yourObject.Credentials = new System.Net.NetworkCredential(username, password);,您尝试过吗?
  • 我不确定您所说的yourObject 是什么意思。我正在尝试使用HttpClient。我实际上创建了一个服务引用,它大大简化了事情,但我应该能够使用HttpClient 而只是将服务引用用于请求和响应对象。我只是在语法上有问题,因为我不知道所有这些对象如何转换为标记。
  • 如果您使用HttpClient 作为请求对象,那么只需attach the credentials like this
  • 如果这不起作用,您确实需要分两步进行发送,首先发送身份验证,等待回复,然后发送您的正常请求(通常带有带有响应的标头您从身份验证中获得)...
  • @Pittfall 你知道 SOAP 标头是消息信封的一部分,它作为请求正文的端口发送,与 HTTP 请求授权标头无关?

标签: c# web-services soap httpclient


【解决方案1】:

鉴于提供的 OP,已完成以下单元测试,以证明您如何填充标头消息标头并创建请求。

[TestClass]
public class SOAP_UnitTests {
    private HttpMethod method;
    private string uri;
    private string action;

    [TestMethod]
    public void _Add_SOAP_Auth_Header_Details_With_HttpRequestMessage() {
        string username = "TheUserName";
        string password = "ThePassword";

        var xml = ConstructSoapEnvelope();
        var doc = XDocument.Parse(xml);
        var authHeader = doc.Descendants("{http://www.test.com/testing/Security}AuthenticationHeader").FirstOrDefault();
        if (authHeader != null) {
            authHeader.Element(authHeader.GetDefaultNamespace() + "UserName").Value = username;
            authHeader.Element(authHeader.GetDefaultNamespace() + "Password").Value = password;
        }
        string envelope = doc.ToString();

        var request = CreateRequest(method, uri, action, doc);
        request.Content = new StringContent(envelope, Encoding.UTF8, "text/xml");

        //request is now ready to be sent via HttpClient
        //client.SendAsync(request);
    }

    private static HttpRequestMessage CreateRequest(HttpMethod method, string url, string action, XDocument soapEnvelopeXml) {
        var request = new HttpRequestMessage(method: method, requestUri: url);
        request.Headers.Add("SOAPAction", action);
        request.Headers.Add("ContentType", "text/xml;charset=\"utf-8\"");
        request.Headers.Add("Accept", "text/xml");
        request.Content = new StringContent(soapEnvelopeXml.ToString(), Encoding.UTF8, "text/xml"); ;
        return request;
    }

    private string ConstructSoapEnvelope() {
        var message = @"<?xml version='1.0' encoding='utf-8'?>
<soap:Envelope xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xmlns:xsd='http://www.w3.org/2001/XMLSchema' xmlns:soap='http://schemas.xmlsoap.org/soap/envelope/'>
  <soap:Header>
    <AuthenticationHeader xmlns='http://www.test.com/testing/Security'>
      <UserName>string</UserName>
      <Password>string</Password>
    </AuthenticationHeader>
  </soap:Header>
  <soap:Body>
    <GetMeSomething xmlns='http://www.test.com/testing/WorkFileCatalog'>
      <Param1>string</Param1>
      <Param2>string</Param2>
      <XMLRetMess>string</XMLRetMess>
    </GetMeSomething>
  </soap:Body>
</soap:Envelope>
";
        return message;
    }
}

【讨论】:

    【解决方案2】:

    如果您使用HttpClient 发布请求,那么您应该构建完整的 XML 请求。

    换句话说,您将构建包含所有元素的确切 Soap XML

    string requestXml = your actual full soap xml
    string result = HttpClient.Post ( your actual xml )
    

    【讨论】:

    • 请删除这个答案,我不是要冒犯你,但这是一个黑客,而不是我想要的。它可能有效,但我想使用 .NET 中提供的对象。一旦协议发生变化,这样做就会失败。
    • 嗯...对于非常简单的 Soap 请求,这是一种非常有效的方法。到目前为止,我们使用它并且对它感到满意。恕我直言,这完全取决于上下文。
    • 我并不是说它不起作用,我只是说它不是一个好的解决方案。让我举一个例子。想象一下使用string s = ""string s = string.Empty。这两种解决方案都有效,但如果空字符串的值从"" 更改为"|"string.Empty 将被更新。现在这个例子可能是基于一些永远不会改变的东西,但我希望你能明白。
    猜你喜欢
    • 1970-01-01
    • 2016-03-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-04-14
    • 2014-08-08
    • 2014-06-02
    相关资源
    最近更新 更多