[.NET][C#]dotNet使用WSE3.0調用java的web服務

本文主要描述使用.net客戶端調用java寫的服務端的webservice,並且使用了WSI協議中的UserNameToken驗證方法。

 

先給出要POST的包格式:

  1. <soap:Envelope xmlns:soap="…">
  2.     <soap:Header>
  3.         <wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
  4.             <wsse:UsernameToken xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" wsu:Id="SecurityToken-7f2cd499-d67d-4052-87c3-870833c2fb06">
  5.                 <wsse:Username>much</wsse:Username>
  6.                 <wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">123456</wsse:Password>
  7.             </wsse:UsernameToken>
  8.         </wsse:Security>
  9.         <RequestSOAPHeader xmlns="….">
  10.             < otherheader>xxxx</otherheader>
  11.         </RequestSOAPHeader>
  12.     </soap:Header>
  13.     <soap:Body>
  14.         ……..
  15.     </soap:Body>
  16. </soap:Envelope>

安裝WSE3.0版本。在VS項目中添加Microsoft.Web.Services3的引用。.

<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />

 

首先,導入有java服務端生成的wsdl文件,生成客戶段代理類。

這裏導入wsdl文件有兩種方法:

一、VS提供的命令提示符中編譯WSDL文件。

給個例子:

Wsdl /language:CS /n:mynamespace /out:myProxyClass.cs C:/myProject/wsdl/webservice.wsdl

最後一個參數是本地的絕對路徑,是一個文件,也可以是一個網絡路徑。

二、在項目右鍵中添加WEB引用,輸入本地的WSDL的絕對路徑。

 

注意:用VS引用生成的代理類名稱爲Reference.cs,可以在項目目錄下找到。

 

然後,修改本地生成的代理類,在最後一個using下面添加

  1. [System.Xml.Serialization.XmlTypeAttribute(Namespace = "…")]
  2. [System.Xml.Serialization.XmlRootAttribute(Namespace = "…", IsNullable = false)]
  3. public class RequestSOAPHeader : System.Web.Services.Protocols.SoapHeader
  4. {
  5.     public string otherheader;
  6. }       

System.Web.Services.Protocols.SoapHttpClientProtocol替換爲Microsoft.Web.Services3.WebServicesClientProtocol

 

在代理類的構造函數上面,private bool useDefaultCredentialsSetExplicitly這行代碼下面添加public RequestSOAPHeader ServiceAuthHeaderValue這行代碼,注意要在類的裏面,作爲服務類的公共對象。

最後,找到你要調用的那個服務方法,在上面添加

[System.Web.Services.Protocols.SoapHeaderAttribute("ServiceAuthHeaderValue")]這行代碼,注意ServiceAuthHeaderValue是聲明的公共成員。

如果你找不到,你可以搜索下類似[System.Web.Services.Protocols.SoapDocumentMethodAttribute("", Use=System.Web.Services.Description.SoapBindingUse.Literal, ParameterStyle=System.Web.Services.Protocols.SoapParameterStyle.Bare)]的代碼。對,就在這上面或下面添加。

如果你看了上面的這些還不是很理解,可以參考下面的例子(根據一個網友提供的資料整理,省略部分代碼)

  1. sing System;
  2. using System.ComponentModel;
  3. using System.Diagnostics;
  4. using System.Web.Services;
  5. using System.Web.Services.Protocols;
  6. using System.Xml.Serialization;
  7. //  
  8. // 此源代碼由 wsdl 自動生成, Version=2.0.50727.1432。 
  9. //  
  10. [System.Xml.Serialization.XmlTypeAttribute(Namespace = "…")] 
  11. [System.Xml.Serialization.XmlRootAttribute(Namespace = "…", IsNullable = false)] 
  12. public class RequestSOAPHeader : System.Web.Services.Protocols.SoapHeader 
  13.     public string otherheader; 
  14. }
  15. /// <remarks/> 
  16. [System.CodeDom.Compiler.GeneratedCodeAttribute("wsdl""2.0.50727.1432")]
  17. [System.Diagnostics.DebuggerStepThroughAttribute()]
  18. [System.ComponentModel.DesignerCategoryAttribute("code")]
  19. [System.Web.Services.WebServiceBindingAttribute(Name="SendMessageBinding", Namespace="http://www.xxx.com.cn")]
  20. public partial class SendMessageBinding : Microsoft.Web.Services3.WebServicesClientProtocol {
  21.     
  22.     private System.Threading.SendOrPostCallback sendMessageOperationCompleted;
  23.     
  24.     private System.Threading.SendOrPostCallback getMessageDeliveryStatusOperationCompleted;
  25.     
  26.     public RequestSOAPHeader ServiceAuthHeaderValue;
  27.     
  28.     /// <remarks/> 
  29.     public SendMessageBinding() {
  30.         this.Url = "http://www.xxx.com.cn";
  31.     }
  32.     
  33.     /// <remarks/> 
  34.     public event sendMessageCompletedEventHandler sendMessageCompleted;
  35.     
  36.     /// <remarks/> 
  37.     public event getMessageDeliveryStatusCompletedEventHandler getMessageDeliveryStatusCompleted;
  38.     
  39.     /// <remarks/> 
  40.     [System.Web.Services.Protocols.SoapHeaderAttribute("ServiceAuthHeaderValue")]
  41.     [System.Web.Services.Protocols.SoapDocumentMethodAttribute("", Use=System.Web.Services.Description.SoapBindingUse.Literal, ParameterStyle=System.Web.Services.Protocols.SoapParameterStyle.Bare)]
  42.     [return: System.Xml.Serialization.XmlElementAttribute("sendMessageResponse", Namespace="http://www.xxx.com.cn")]
  43.     public sendMessageResponse sendMessage([System.Xml.Serialization.XmlElementAttribute("sendMessage", Namespace="http://www.xxx.com.cn")] sendMessage sendMessage1) {
  44.         object[] results = this.Invoke("sendMessage"new object[] {
  45.                     sendMessage1});
  46.         return ((sendMessageResponse)(results[0]));
  47.     }
  48. ......

到這裏就修改好了代理類了,注意保存備份下,不要更新代理類,否則,代理類又會還原回去了。

 

接着設置下WSE的配置,右擊項目選擇WSE settings 3.0…

勾選General下的Enable this project for web service enhancements

選擇Policy,勾選Enable Policy,然後點Add,我這裏已經添加了,沒添加的時候是空的。

填寫Policy的名稱爲ClientPolicy,在嚮導中,依次選擇Secure a client application+username ->Specify username token in code ->None

最後生成的Policy信息如下:

然後到Security選項卡里點擊Security Tokens Managers中的Add,在下拉框中選擇Username Token Manager,會自動生成其他的信息,點OK保存即可。

 

看下你的app.config中有沒有如下信息:

  1. <configSections>
  2.     <section name="microsoft.web.services3" type="Microsoft.Web.Services3.Configuration.WebServicesConfiguration, Microsoft.Web.Services3, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
  3.    …….
  4.     </sectionGroup>
  5.   </configSections>
  6.   <microsoft.web.services3>
  7.     <policy fileName="wse3policyCache.config" />
  8.     <security>
  9.       <securityTokenManager>
  10.         <add type="Microsoft.Web.Services3.Security.Tokens.UsernameTokenManager, Microsoft.Web.Services3, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" namespace="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" localName="UsernameToken" />
  11.       </securityTokenManager>
  12.     </security>  
  13.   </microsoft.web.services3>

wse3policyCache.config裏的信息如下:

  1. <policies xmlns="http://schemas.microsoft.com/wse/2005/06/policy">
  2.   <extensions>
  3.      <extension name="requireActionHeader" type="Microsoft.Web.Services3.Design.RequireActionHeaderAssertion, Microsoft.Web.Services3, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
  4.     <extension name="usernameOverTransportSecurity" type="Microsoft.Web.Services3.Design.UsernameOverTransportAssertion, Microsoft.Web.Services3, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
  5.   </extensions>
  6.   <policy name="ClientPolicy">
  7.     <usernameOverTransportSecurity />
  8.     <requireActionHeader />
  9.      </policy>
  10. </policies>

下面是調用服務方法的關鍵代碼:

  1. //服務對象
  2. ProxyService sendws = new ProxyService();
  3. //添加SOAP頭
  4. ProxyService.RequestSOAPHeader Soapheader = new ProxyService.RequestSOAPHeader();
  5. Soapheader.otherheader=”xxx”;
  6. sendws.ServiceAuthHeaderValue = Soapheader; 
  7. //設置協議
  8. UsernameToken token = new UsernameToken("username""password", PasswordOption.SendPlainText);
  9. sendws.SetClientCredential(token);
  10. sendws.SetPolicy("ClientPolicy");
  11. sendws.Url = ".....";
  12. sendws.webmethod ();

到這裏使用Fiddler截包,發現SOAP包頭中的信息出現了Action, Timestamp等信息,爲了得到更加靈活的SOAP頭,就必須重寫SoapFilter類。

 

在你的項目中添加一個類UsernameClientAssertion

  1. class UsernameClientAssertion : SecurityPolicyAssertion
  2.     {
  3.         public string UserName;
  4.         public string PassWord;
  5.         public UsernameClientAssertion(string UserName, string PassWord)
  6.         {
  7.             this.UserName = UserName;
  8.             this.PassWord = PassWord;
  9.         }
  10.         public override SoapFilter CreateClientOutputFilter(FilterCreationContext context)
  11.         {
  12.             return new ClientOutputFilter(this, context);
  13.         }
  14.         public override SoapFilter CreateClientInputFilter(FilterCreationContext context)
  15.         {
  16.             return null;
  17.         }
  18.         public override SoapFilter CreateServiceInputFilter(FilterCreationContext context)
  19.         {
  20.             return null;
  21.         }
  22.         public override SoapFilter CreateServiceOutputFilter(FilterCreationContext context)
  23.         {
  24.             return null;
  25.         }
  26. }

新建一個ClientOutputFilter

  1. class ClientOutputFilter : SoapFilter 
  2. {
  3.         private UsernameClientAssertion parentAssertion;
  4.         private FilterCreationContext filterContext;        
  5.         public ClientOutputFilter(UsernameClientAssertion parentAssertion, FilterCreationContext filterContext)
  6.         {
  7.             this.parentAssertion = parentAssertion;
  8.             this.filterContext = filterContext;
  9.         }
  10.         public override Microsoft.Web.Services3.SoapFilterResult ProcessMessage(SoapEnvelope envelope)
  11.         {
  12.             XmlElement securityElement = envelope.CreateElement("wsse""Security""http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd");
  13.             XmlAttribute mustUnderstandAttribute = envelope.CreateAttribute(envelope.DocumentElement.Prefix,
  14.                 "mustUnderstand", envelope.DocumentElement.NamespaceURI);
  15.             mustUnderstandAttribute.Value = "true";
  16.             UsernameToken userToken = new UsernameToken(parentAssertion.UserName, parentAssertion.PassWord, PasswordOption.SendPlainText);
  17.                         
  18.             securityElement.AppendChild(userToken.GetXml(envelope));            
  19.             securityElement.FirstChild.RemoveChild(securityElement.FirstChild.FirstChild.NextSibling.NextSibling);
  20.             securityElement.FirstChild.RemoveChild(securityElement.FirstChild.FirstChild.NextSibling.NextSibling);                        
  21.             //envelope.CreateHeader().RemoveAll();
  22.             envelope.CreateHeader().PrependChild(securityElement);
  23.             envelope.CreateHeader().RemoveChild(envelope.CreateHeader().FirstChild.NextSibling.NextSibling);
  24.             envelope.CreateHeader().RemoveChild(envelope.CreateHeader().FirstChild.NextSibling.NextSibling);
  25.             envelope.CreateHeader().RemoveChild(envelope.CreateHeader().FirstChild.NextSibling.NextSibling);
  26.             envelope.CreateHeader().RemoveChild(envelope.CreateHeader().FirstChild.NextSibling.NextSibling);            
  27.             return SoapFilterResult.Continue;
  28.         }
  29. }

簡單說下上面的代碼,創建靈活的SOAP頭就在方法public override Microsoft.Web.Services3.SoapFilterResult ProcessMessage(SoapEnvelope envelope)裏,

可以看得出就是對XML的操作啦,如果調不出你要的包,就設個斷點F10F10。。。

 

修改下原來的代碼爲:

  1. //服務對象
  2. ProxyService sendws = new ProxyService();
  3. //添加SOAP頭
  4. ProxyService.RequestSOAPHeader Soapheader = new ProxyService.RequestSOAPHeader();
  5. Soapheader.otherheader=”xxx”;
  6. sendws.ServiceAuthHeaderValue = Soapheader; 
  7. //設置協議
  8. UsernameToken token = new UsernameToken("username""password", PasswordOption.SendPlainText);
  9. Policy ProvideUsernameToken = new Policy();
  10. ProvideUsernameToken.Assertions.Add(new UsernameClientAssertion("domain_user""domain_user"));
  11. UsernameTokenManager tokenm = new UsernameTokenManager();
  12. sendws.SetClientCredential(token);
  13. sendws.SetPolicy(ProvideUsernameToken);
  14. sendws.Url = "...";
  15. sendws.webmethod ();

這樣就重寫了SOAP頭的輸出部分了。

 

總結

WSE3.0只能在VS2005下才能集成在項目中,VS2008不能支持,我之前試着直接改寫app.configwse3policyCache.config裏的內容都失敗了,覺得可能是證書的生成有問題,WSE也提供手動生成證書,但是這麼多東西都用手動生成,恐怕不太容易,稍有差錯就調試不出來了。

VS2008下已經使用WCF代替了WSE了,使用了綁定設置的方法,我也沒有試出來,如果你試出來了,請告訴我,謝謝。

 

修訂:

1.添加代理類例子 2008-10-15

2.修改標題,方便搜索的到 2008-11-15

 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章