对于如何创建SOAP <wsse:security> header </wsse:security>一无所知

时间:2009-04-09 13:54:29

标签: c# .net soap

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

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

我还发现一条线索,如果使用WS2005,可能会生成标头,因为它有WS3插件。有谁评论这个?快速浏览一下这个插件后,我在Security头中找到了simmilar字段,但仍然无法创建标题。

6 个答案:

答案 0 :(得分:12)

我们可以使用以下代码解决它:

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框所需的标题。

如何使用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());
        }
    }

答案 1 :(得分:6)

有趣的是你应该提一下 - 我最近一直在做

我设法使用SoapExtension使用ChainStream来保留原始流的副本,只是在BeforeDeserialize期间复制流并在{{{}期间添加标头1}}。

添加标题是将“新”流(从AfterSerialize返回)的内容读入XML文档(在我的情况下为ChainStream),添加标题,然后写入它传递到原始流XDocument

不幸的是,这很脏,而且你不能(据我所知)在需要时使用具有适当身份验证信息的新实例。

我使用ChainStream代替大多数,为Web服务的每个方法添加适当的属性,并为具有实例的适当字段/属性添加适当的属性必需的标题 - 但是SOAP序列化目前在指定正确的元素名称(使用名称空间)方面让我感到头痛。这是我一直计划在有空的时候问别人的事情。

很抱歉不能给你一个完整的答案 - 并且对于缺少代码而道歉,它属于公司而不是我 - 但希望它至少会给你一个起点。

答案 2 :(得分:5)

通常很容易将SOAP标头添加到.Net中的Web服务代理中。这是一个快速的代码示例。

创建新的SOAP标头

using System.Web.Services.Protocols;

public class SoapAuthHeader : SoapHeader
{
public string Username;
public string Password;
}

在您的网络服务代理类中:

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;

编辑:还有其他方法,微软确实有WSE library包括WS-Security,它提供了比上面简单示例更多的功能。如果您需要在SOAP标头中使用Kerberos令牌或证书签名,那么就可以了。如果您需要为通过SSL运行的Web服务添加简单的用户名和密码,那么可能就是您所需要的。

编辑: WSE上的快速模糊此十年前,当Web服务将接管世界时,一群行业参与者(微软,IBM,Sun等)聚集在一起提出标准对他们做事的方式。形成的身体是OASIS。从那时起,微软已经发布了许多版本的WSE库来支持一些规范,但有趣的是,即使第一个版本在2003年左右公开,它们也从未被整合到.Net框架中。

Web服务虽然仍然非常受欢迎,但在我看来,在不同的互联网应用程序之间集成的一种很好的方式已经有点失宠了。其中一个原因无疑是因为AJAX和网络服务不是最好的床位研究员,尽管这已经有所改善。一旦你开始包含所有额外的sWSE规范,其中一个瘦的web服务被解决就是其他RPC协议,CORBA等的复杂性,Web服务也会变得相当复杂。与此同时,REST已经获得了很多人气Web服务和AJAX库通常更喜欢它。

Web服务不会很快消失,但它们很可能不会很快接管世界。

答案 3 :(得分:1)

有一个名为ClearUserNameBinding的开源自定义Binding,这个绑定有助于在Http上将UserNameToken作为clearText传递。当使用WCF cllient需要使用基于java的Web服务时,这帮助了我。

http://code.google.com/p/wcf-clear-username-binding/ http://webservices20.blogspot.com/2008/11/introducing-wcf-clearusernamebinding.html

答案 4 :(得分:1)

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

类:

 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
                        }
                    }

答案 5 :(得分:0)

Domenico Zinzi 的解决方案为我做出了以下修改: 我在SecurityHeader类中创建了一个构造函数:

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

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

messageHeadersElement.Add(New SecurityHeader("UserName", "Password"))

它奏效了:)

P.S。无法将其添加为注释,这就是为什么在此处添加它。