C# 对如何创建SOAP一无所知<;wsse:安全性>;标题

C# 对如何创建SOAP一无所知<;wsse:安全性>;标题,c#,.net,soap,C#,.net,Soap,我几乎没有使用SOAP协议的经验。我需要连接到所需标头的服务。我认为这在Java中有点标准,但在C中,必须手动创建此标头 这里有没有人能够连接到类似的服务:已经创建了标题,或者甚至可能知道一些标准库,可以简化标题的创建?你能分享一些代码或参考资料吗 我还发现,如果使用WS2005,可能会生成头文件,因为它有WS3插件。有人能对此发表评论吗?快速查看此加载项后,我发现类似于Security header的字段,但仍然无法创建header。有趣的是,您应该提到这一点-我最近一直在做这件事 我使用So

我几乎没有使用SOAP协议的经验。我需要连接到所需标头的服务。我认为这在Java中有点标准,但在C中,必须手动创建此标头

这里有没有人能够连接到类似的服务:已经创建了标题,或者甚至可能知道一些标准库,可以简化标题的创建?你能分享一些代码或参考资料吗


我还发现,如果使用WS2005,可能会生成头文件,因为它有WS3插件。有人能对此发表评论吗?快速查看此加载项后,我发现类似于Security header的字段,但仍然无法创建header。

有趣的是,您应该提到这一点-我最近一直在做这件事

我使用
SoapExtension
实现了这一点,它使用
ChainStream
保留原始流的副本,只需在
反序列化之前复制流,并在
反序列化之后添加头

添加标题是将“新”流(从
ChainStream
返回)的内容读取到XML文档(在我的例子中是
XDocument
)中,添加标题,然后将其写入传递到
ChainStream
中的原始流

不幸的是,这是非常肮脏的,而且(据我所知)在需要的时候,您不能使用带有适当身份验证信息的新实例

大多数情况下,我使用的是
SoapHeader
,为web服务的每个方法添加一个适当的属性,以及一个带有所需头实例的适当字段/属性,但SOAP序列化目前让我头疼的是指定正确的元素名(使用名称空间)。这是我一直计划在有时间的时候问别人的事情


很抱歉不能给你一个完整的答案,同时也为缺少代码表示歉意,它属于公司而不是我,但希望它至少能给你一个起点。

在.Net中向web服务代理添加SOAP头通常非常容易。下面是一个快速代码示例

创建一个新的SOAP头

using System.Web.Services.Protocols;

public class SoapAuthHeader : SoapHeader
{
public string Username;
public string Password;
}
在web服务代理类中:

public class MyWebServicesProxy : System.Web.Services.Protocols.SoapHttpClientProtocol {

    public SoapAuthHeader AuthHeader;

    ...

}
然后使用:

SoapAuthHeader authHeader = new SoapAuthHeader();
authHeader.Username = "username";
authHeader.Password = "password";

MyWebServicesProxy myProxy = new MyWebServicesProxy();
myProxy.AuthHeader = authHeader;
编辑:还有其他方法可以做到这一点,微软确实有一个包含WS-Security的应用程序,与上面的简单示例相比,taht提供了更多的功能。如果您需要在SOAP头中使用Kerberos令牌或证书签名,那么这就是最好的选择。如果您需要为通过SSL运行的web服务添加一个简单的用户名和密码,那么exmaple可能就是您所需要的全部

编辑:关于WSE的快速宣传本世纪初,当web服务即将接管世界时,一群行业参与者(Microsoft、IBM、Sun等)聚集在一起,提出了标准的方法来处理这些问题。尸体形成了。从那时起,微软已经发布了许多版本的WSE库来支持一些规范,但有趣的是,尽管第一个版本在2003年左右公开,它们从未被纳入到.Net框架中

Web服务虽然仍然非常流行,而且在我看来,集成不同internet应用程序的一种好方法已经有点不受欢迎了。其中一个原因无疑是因为AJAX和web服务不是最好的伙伴,尽管这已经有所改善。一旦您开始包含所有额外的sWSE规范,Web服务也会变得非常复杂,支持Web服务解决的问题之一是其他RPC协议、CORBA等的复杂性。与此同时,REST以牺牲Web服务和AJAX库为代价获得了大量流行


Web服务无论如何都不会很快消失,但它们也可能不会很快接管世界。

有一个开源自定义绑定称为ClearUserNameBinding,该绑定有助于在Http上以明文形式传递UserNameToken。当需要使用WCF客户机使用基于java的web服务时,这帮助了我


我们可以通过以下代码解决此问题:

public class SecurityHeader : System.ServiceModel.Channels.MessageHeader {
    public string userName;
    public string password;

    protected override void OnWriteStartHeader (System.Xml.XmlDictionaryWriter writer, System.ServiceModel.Channels.MessageVersion messageVersion)
    {
        writer.WriteStartElement("wsse", Name, Namespace);
        writer.WriteXmlnsAttribute("wsse", Namespace);
    }

    protected override void OnWriteHeaderContents (System.Xml.XmlDictionaryWriter writer, System.ServiceModel.Channels.MessageVersion messageVersion)
    {
        writer.WriteStartElement("wsse", "UsernameToken", Namespace);

        writer.WriteStartElement("wsse", "Username", Namespace);
        writer.WriteValue(userName);
        writer.WriteEndElement();

        writer.WriteStartElement("wsse", "Password", Namespace);
        writer.WriteValue(password);
        writer.WriteEndElement();

        writer.WriteEndElement();

    }

    public override string Name
    {
        get { return "Security"; }
    }

    public override string Namespace
    {
        get { return "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"; }
    }
}
这写入了DataPower box所需的标头

如何使用SecurityHeader类

    public static void Main(string[] args)
    {

        var webService = new ServiceReference1.MyWebService();
        ....
       webService.Open();


        using (OperationContextScope scope = new OperationContextScope((IContextChannel)webService.InnerChannel))
        {

            var myObjRequest = GetMyObjRequest();

            MessageHeaders messageHeadersElement = OperationContext.Current.OutgoingMessageHeaders;
            messageHeadersElement.Add(SecurityHeader("UserName", "Password"))


             var res = webService.MyServe(myObjRequest);
            Console.WriteLine(res.ToString());
        }
    }

多梅尼科·辛齐的解决方案为我提供了以下修改: 我在SecurityHeader类中创建了一个构造函数:

public SecurityHeader(字符串用户名、字符串密码){
用户名=用户名;
密码=密码;
}

在调用它时,我使用了“New”关键字,如下所述:

messageHeadersElement.Add(新的SecurityHeader(“用户名”、“密码”))

它成功了:)


请注意,无法将此添加为评论,这就是为什么要将其添加到此处。

谢谢各位。您所有的代码和想法收集如下

类别: 使用:
就我所知,WSE不适用于VisualStudio2008,这真的很烦人。SoapHeader路由在理论上是不错的,但在我的特殊情况下,我在为标头中的元素获取正确的命名空间时遇到了一个问题:(@Jon:好吧,这太糟糕了。我过去曾有过一次不得不深入研究远程处理和SOAP序列化链的经历,虽然这并不难,但它肯定没有创建自定义标题或WSE那么优雅。我只是想说清楚,我找到了属于我自己类型的元素,我可以使用SoapTypeAttribute和指定名称/名称空间。SoapElementAttribute中缺少名称空间属性,这让我很头疼:(你能告诉我更多关于WSE库的信息吗?@VoodooChild最初的问题是关于SOAP的,SOAP是WCF可以使用的传输层之一。在提出这个问题后的6.5年里,除了我自己托管的WCF服务之外,WCF确实使集成web服务的某些方面变得更容易了
 public class SecurityHeader : System.ServiceModel.Channels.MessageHeader
{
    public string userName;
    public string password;

    public SecurityHeader(string userName, string password)
    {
        this.userName = userName;
        this.password = password;
    }

    protected override void OnWriteStartHeader(System.Xml.XmlDictionaryWriter writer, System.ServiceModel.Channels.MessageVersion messageVersion)
    {
        writer.WriteStartElement("wsse", Name, Namespace);
        writer.WriteXmlnsAttribute("wsse", Namespace);
    }

    protected override void OnWriteHeaderContents(System.Xml.XmlDictionaryWriter writer, System.ServiceModel.Channels.MessageVersion messageVersion)
    {
        writer.WriteStartElement("wsse", "UsernameToken", Namespace);
        writer.WriteStartElement("wsse", "Username", Namespace);
        writer.WriteValue(userName);
        writer.WriteEndElement();
        writer.WriteStartElement("wsse", "Password", Namespace);
        writer.WriteAttributeString("Type", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText");
        writer.WriteValue(password);
        writer.WriteEndElement();
        writer.WriteEndElement();
    }

    public override string Name
    {
        get { return "Security"; }
    }

    public override string Namespace
    {
        get { return "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"; }
    }
}
     using (IdsTestSvc.MedulaIlacDagitimSistemiIslemleriClient client = new IdsTestSvc.MedulaIlacDagitimSistemiIslemleriClient("MedulaIlacDagitimSistemiIslemleriPort"))
                    {
                        using (OperationContextScope scope = new OperationContextScope(client.InnerChannel))
                        {
                            MessageHeaders messageHeadersElement = OperationContext.Current.OutgoingMessageHeaders;
                            messageHeadersElement.Add(new SecurityHeader(_main.IdsFirmCode, _main.IdsFirmCode));
 ....Do something
                        }
                    }