【问题标题】:Can't authenticate towards SOAP service in ASP.NET Core无法对 ASP.NET Core 中的 SOAP 服务进行身份验证
【发布时间】:2017-09-19 10:30:26
【问题描述】:

我正在尝试使用 ASP.NET Core 库项目中的 SOAP Web 服务。

我已经安装了 Mictosoft WCF Web 服务参考提供程序,它为我创建了代理类,但我遇到了身份验证问题。

我的代码目前如下所示:

var binding = new BasicHttpBinding(BasicHttpSecurityMode.TransportWithMessageCredential);

var address = new EndpointAddress(@"https://myserviceaddress.asmx");
var client = new TestApiClient(binding, address);
client.ClientCredentials.UserName.UserName = "testusername";
client.ClientCredentials.UserName.Password = "testpassword";
var result = await client.GetDataAsync(params);

我尝试了一些不同的方法,但我要么未经授权,要么得到以下变体:The value 'TransportWithMessageCredential' is not supported in this context for the binding security property 'securityMode'.

我想我也应该在binding.Security.Message 上设置一些属性,但binding.Security 上存在的唯一属性是TransportMode

有人知道如何正确设置吗?

还有其他更好的方法来使用 ASP.NET Core 的 SOAP 服务吗?我喜欢一种不必创建代理类的动态方式,但如果必须的话,我可以使用代理,但我需要能够使用用户和密码进行身份验证,而且我必须使用 https。

【问题讨论】:

  • .NET Core 似乎不支持TransportWithMessageCredentialgithub.com/dotnet/wcf/issues/8
  • @ØyvindBråthen,你有没有得到这个?我被困在同一个问题上。
  • @ØyvindBrå那你能解决这个问题吗?

标签: c# authentication asp.net-core soap


【解决方案1】:

在同一个问题上苦苦挣扎了很多天之后,由于.Net core 到此答案为止的支持非常有限,我设法通过自己构建整个信封并使用SimpleSoapClient 来解决它。

我将尝试通过一个简单的示例逐步完成所有需要的步骤。因为每一步都有自己的问题需要解决。

让我们假设您的模型是猫。

 public class Cat
    {
        public int Lives { get; set; }
    }

您的整个包络模型将如下所示:

public class Envelope
{
    public EnvelopeHeader Header { get; set; }
    public EnvelopeBody Body { get; set; }
}
public class EnvelopeHeader
{
    [XmlElementAttribute(Namespace = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd")]
    public Security Security { get; set; }
}


[XmlTypeAttribute(AnonymousType = true, Namespace = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd")]
[XmlRootAttribute(Namespace = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd", IsNullable = false)]
public class Security
{
    public SecurityUsernameToken UsernameToken { get; set; }
}


[XmlTypeAttribute(AnonymousType = true, Namespace = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd")]
public  class SecurityUsernameToken
{
    public string Username { get; set; }
    public SecurityUsernameTokenPassword Password { get; set; }
    [XmlAttributeAttribute(Form = System.Xml.Schema.XmlSchemaForm.Qualified, Namespace = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd")]
    public string Id { get; set; }
}


[XmlTypeAttribute(AnonymousType = true, Namespace = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd")]
public  class SecurityUsernameTokenPassword
{
    [XmlAttributeAttribute()]
    public string Type { get; set; }
    [XmlTextAttribute()]
    public string Value { get; set; }
}

public  class EnvelopeBody
{
    public Cat Cat{ get; set; }
}

P.S:不要忘记在你的身体需要的地方包含 XML 命名空间。

下一步是将您的 Envelop 模型序列化为 XML 字符串。

string xml;
XmlWriterSettings settings = new XmlWriterSettings();
settings.OmitXmlDeclaration = true;
using (MemoryStream ms = new MemoryStream())
  {
    using (XmlWriter writer = XmlWriter.Create(ms, settings))
     {
       XmlSerializerNamespaces names = new XmlSerializerNamespaces();
       names.Add("", "");//add your needed namespaces here
       XmlSerializer cs = new XmlSerializer(typeof(Envelope));
       var myEnv = new Envelope()
        {
         Header = new EnvelopeHeader()
          {
           Security = new Security()
            {
              UsernameToken = new SecurityUsernameToken()
               {
                Username = "",
                Password = new SecurityUsernameTokenPassword()
                {
                 Type = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText",//update type to match your case
                 Value = ""
                }
               }
              }
             },
             Body = new EnvelopeBody()
             {
              Cat = new Cat() { Lives = 7 }
             }
            };
            cs.Serialize(writer, myEnv, names);
            ms.Flush();
            ms.Seek(0, SeekOrigin.Begin);
            StreamReader sr = new StreamReader(ms);
            xml = sr.ReadToEnd();
          }
     }

最后使用以下方式发送您的 XML 信封:

  SoapEnvelope responseEnvelope = null;
        using (var client = SoapClient.Prepare().WithHandler(new DelegatingSoapHandler()
        {
            OnHttpRequestAsyncAction = async (z, x, y) =>
            {
                x.Request.Content = new StringContent(xml , Encoding.UTF8, "text/xml");
            }
        }))
        {
                responseEnvelope = client.SendAsync("url", "action",SoapEnvelope.Prepare()).Result;
        }

请注意,您需要根据您的情况更新许多选项。 我的案例是带有 WCF 的 WSSE 安全标头中类型为“PasswordText”的密码。

【讨论】:

    【解决方案2】:

    .NET Core 2.0 上的 WCF 尚不支持消息安全性(BasicHttpBinding 上的TransportWithMessageCredential)。

    参考:

    【讨论】:

    • 根据 github 更新:现在支持 BasicHttpBinding 上的 TransportWithMessageCredential 模式
    【解决方案3】:

    您是否尝试过在 IIS 上启用 SSL?启用 SSL 将使您的服务同时侦听 HTTP 和 HTTPS。您的客户需要购买 SSL 证书。为此

    【讨论】:

    • 这不是我的服务。这是我想使用的外部服务,所以这对我没有多大帮助。
    猜你喜欢
    • 1970-01-01
    • 2012-05-05
    • 1970-01-01
    • 1970-01-01
    • 2014-11-08
    • 1970-01-01
    • 2011-08-29
    • 2020-07-26
    • 2019-08-02
    相关资源
    最近更新 更多