WCF安全性认证:SoapHeader使用HTTP Request调用

Posted petewell

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了WCF安全性认证:SoapHeader使用HTTP Request调用相关的知识,希望对你有一定的参考价值。

WCF安全性认证:SoapHeader(二)使用HTTP Request调用


在前面第一篇介绍的WinFrom Client 端程序为了送出request时要产生SoapHeader﹐而另外撰写了一个ClientHeader类库﹐并且必须在组态加入对应的设定﹐手续看起来有些复杂。实际上﹐有时会希望是以WebRequest的原生方式自行组合Soap 格式数据来进行数据的交换。

在开始之前需要先知道一些数据的规则﹐首先由wsdl规格中可以找到SOAPAction

技术图片

前面的介绍过程中在使用Fiddler观察数据时﹐可以看到送出的标准Soap数据格式﹐这是现在在程序中要自行组合的字符串﹐其中包含了SoapHeader﹐要调用的方法与传递的参数。

技术图片

   1:  
   2:  
   3:      账号
   4:      密码
   5:    
   6:    
   7:      
   8:        test
   9:      
  10:    
  11:  

有了SoapAction和Soap数据的格式﹐接下来就使用三种平台的方式来撰写。

1. .Net 的调用方式

   1:  string wsdlUri = "http://kevin-h:905/basicHttpSoapHeader.host/MyProducts.svc?singleWsdl";
   2:  string username = System.Configuration.ConfigurationManager.AppSettings["username"].ToString();
   3:  string pwd = System.Configuration.ConfigurationManager.AppSettings["pwd"].ToString();
   4:  ?
   5:  private void btnCallSaySomething_Click(object sender, EventArgs e) 
   6:      try 
   7:          HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(wsdlUri);
   8:          webRequest.Method = "POST";
   9:          webRequest.ContentType = "text/xml;charset=UTF-8";
  10:                  webRequest.Headers.Add("SOAPAction:"http://tempuri.org/IProductService/SaySomething"");  //<--SOAPAction 别忘了
  11:          StringBuilder soapStr = new StringBuilder(Environment.NewLine);
  12:          soapStr.Append("" + Environment.NewLine);
  13:          soapStr.Append("  " + Environment.NewLine);
  14:          soapStr.Append("    "+username+"" + Environment.NewLine);
  15:          soapStr.Append("    "+pwd+"" + Environment.NewLine);
  16:          soapStr.Append("  " + Environment.NewLine);
  17:          soapStr.Append("  " + Environment.NewLine);
  18:          soapStr.Append("    " + Environment.NewLine);
  19:          soapStr.Append("      test" + Environment.NewLine);
  20:          soapStr.Append("    " + Environment.NewLine);
  21:          soapStr.Append("  " + Environment.NewLine);
  22:          soapStr.Append("" + Environment.NewLine);
  23:  ?
  24:          byte[] buffer = Encoding.UTF8.GetBytes(soapStr.ToString());
  25:          webRequest.ContentLength = buffer.Length;
  26:          Stream post = webRequest.GetRequestStream();
  27:          post.Write(buffer, 0, buffer.Length);
  28:          post.Close();
  29:  ?
  30:          HttpWebResponse response;
  31:          response = (HttpWebResponse)webRequest.GetResponse();
  32:          Stream respostData = response.GetResponseStream();
  33:          StreamReader sr = new StreamReader(respostData);
  34:          string strResponseXml = sr.ReadToEnd();
  35:  ?
  36:          txtOutputValue.Text = strResponseXml;
  37:       catch (Exception er) 
  38:          if (er.InnerException != null) 
  39:              txtSaySomethingMsg.Text = "InnerException:" + er.InnerException.Message;
  40:           else 
  41:              txtSaySomethingMsg.Text = "Exception:" + er.Message;
  42:          
  43:      
  44:  

上述的程序执行之后所得到的结果为以下的XML格式数据﹐只要Parse这个数据就可以得到想要的东西。

   1:  
   2:  
   3:      
   4:          You say [test].
   5:      
   6:  
   7:  

2. Java 的调用方式

   1:  package wcf.com;
   2:  ?
   3:  import java.io.BufferedReader;
   4:  import java.io.ByteArrayOutputStream;
   5:  import java.io.InputStreamReader;
   6:  import java.io.OutputStream;
   7:  import java.net.HttpURLConnection;
   8:  import java.net.URL;
   9:  import java.net.URLConnection;
  10:  ?
  11:  public class wcfClient 
  12:      public static void main(String[] args) 
  13:          String responseString = "";
  14:          String outputString = "";
  15:          String wsURL = "http://kevin-h:905/basicHttpSoapHeader.host/MyProducts.svc?wsdl";
  16:  ?
  17:          try
  18:              URL url = new URL(wsURL);
  19:              URLConnection connection = url.openConnection();
  20:              HttpURLConnection httpConn = (HttpURLConnection)connection;
  21:              ByteArrayOutputStream bout = new ByteArrayOutputStream();
  22:              
  23:              StringBuilder xmlInput=new StringBuilder();
  24:              xmlInput.append("n");
  25:              xmlInput.append("  n");
  26:              xmlInput.append("    testmann");
  27:              xmlInput.append("    a123456n");
  28:              xmlInput.append("  n");
  29:              xmlInput.append("  n");
  30:              xmlInput.append("    n");
  31:              xmlInput.append("      中文字测试n");
  32:              xmlInput.append("    n");
  33:              xmlInput.append("  n");
  34:              xmlInput.append("n");
  35:              
  36:              byte[] buffer=new String(xmlInput).getBytes();
  37:              bout.write(buffer);
  38:              byte[] b = bout.toByteArray();
  39:              String SOAPAction ="http://tempuri.org/IProductService/SaySomething";
  40:              
  41:              //设定适当的Http参数
  42:              httpConn.setRequestProperty("Content-Length",String.valueOf(b.length));
  43:              httpConn.setRequestProperty("Content-Type", "text/xml; charset=utf-8");
  44:              httpConn.setRequestProperty("SOAPAction", SOAPAction);
  45:              httpConn.setRequestMethod("POST");
  46:              httpConn.setDoOutput(true);
  47:              httpConn.setDoInput(true);
  48:              OutputStream out = httpConn.getOutputStream();
  49:              out.write(b);
  50:              out.close();
  51:  ?
  52:              InputStreamReader isr = new InputStreamReader(httpConn.getInputStream());
  53:              BufferedReader in = new BufferedReader(isr);
  54:           
  55:              while ((responseString = in.readLine()) != null) 
  56:                  outputString = outputString + responseString;
  57:              
  58:  ?
  59:              
  60:              System.out.println(outputString);
  61:          catch(Exception er)
  62:              er.printStackTrace();
  63:          
  64:      
  65:  

执行后可以看到输出的结果和前面.Net得到的结果相同﹐接下就要自行parse XML了。

Ps.在使用eclipse撰写时﹐送出request并能正确的接回数据﹐但后来在传递的值改为中文后就一直失败。直觉是编码出了问题﹐查了许久才发现﹐eclipse在windows时文件存档时默认文件格式编码为MS950﹐如果将文件改存为UTF-8则传递中文的问题就解决了。

3. android 的调用方式

时下最流行的移动设备﹐当然也必须要能调用WCF才行﹐以下的示范是以Android 4.2.2版本为例。

在Android 3.0之后在主线程上不能直接进行网络活动﹐否则将会得到NetworkOnMainThreadException错误消息。因此在这里先建立一个SoapObjec的class﹐在主线程上再以另一个Thread来执行。

SoapObject.java

   1:  package com.example.callwcftest;
   2:  ?
   3:  import java.io.IOException;
   4:  ?
   5:  import org.apache.http.HttpEntity;
   6:  import org.apache.http.HttpResponse;
   7:  import org.apache.http.client.ClientProtocolException;
   8:  import org.apache.http.client.ResponseHandler;
   9:  import org.apache.http.client.methods.HttpPost;
  10:  import org.apache.http.entity.ByteArrayEntity;
  11:  import org.apache.http.impl.client.DefaultHttpClient;
  12:  import org.apache.http.params.HttpConnectionParams;
  13:  import org.apache.http.params.HttpParams;
  14:  import org.apache.http.params.HttpProtocolParams;
  15:  import org.apache.http.util.EntityUtils;
  16:  ?
  17:  import android.util.Log;
  18:  ?
  19:  public class SoapObject 
  20:      private String wsURL="";
  21:      private String soapAction="";
  22:      private String soapBody="";
  23:      
  24:      public void setWsURL(String wsURL)
  25:          this.wsURL=wsURL;
  26:      
  27:      
  28:      public void setSoapAction(String soapAction)
  29:          this.soapAction=soapAction;
  30:      
  31:      
  32:      public void setSoapBody(String soapBody)
  33:          this.soapBody=soapBody;
  34:      
  35:  ?
  36:      public String sendRequest()
  37:          String responseString="";
  38:          final DefaultHttpClient httpClient=new DefaultHttpClient();
  39:          // request 参数
  40:            HttpParams params = httpClient.getParams();
  41:            HttpConnectionParams.setConnectionTimeout(params, 10000);
  42:            HttpConnectionParams.setSoTimeout(params, 15000);
  43:          // set parameter
  44:            HttpProtocolParams.setUseExpectContinue(httpClient.getParams(), true);
  45:  ?
  46:            // POST the envelope
  47:            HttpPost httppost = new HttpPost(this.wsURL);
  48:            // add headers
  49:            httppost.setHeader("soapaction", this.soapAction);
  50:            httppost.setHeader("Content-Type", "text/xml; charset=utf-8");
  51:            
  52:          try 
  53:              // the entity holds the request
  54:              // HttpEntity entity = new StringEntity(envelope);
  55:              HttpEntity entity = new ByteArrayEntity(this.soapBody.getBytes("UTF-8"));
  56:              httppost.setEntity(entity);
  57:  ?
  58:              // Response handler
  59:              ResponseHandler rh = new ResponseHandler() 
  60:                  // invoked when client receives response
  61:                  public String handleResponse(HttpResponse response)
  62:                          throws ClientProtocolException, IOException 
  63:                      // get response entity
  64:                      HttpEntity entity = response.getEntity();
  65:  ?
  66:                      // read the response as byte array
  67:                      StringBuffer out = new StringBuffer();
  68:                      byte[] b = EntityUtils.toByteArray(entity);
  69:  ?
  70:                      // write the response byte array to a string buffer
  71:                      out.append(new String(b, 0, b.length));
  72:                      return out.toString();
  73:                  
  74:              ;
  75:  ?
  76:              responseString = httpClient.execute(httppost, rh);
  77:           catch (Exception e) 
  78:              Log.v("exception", e.toString());
  79:          
  80:  ?
  81:          // close the connection
  82:          httpClient.getConnectionManager().shutdown();
  83:          
  84:          return responseString;
  85:      
  86:  

接着撰写主线程的部分

   1:  package com.example.callwcftest;
   2:  ?
   3:  import android.app.Activity;
   4:  import android.os.Bundle;
   5:  import android.util.Log;
   6:  import android.view.Menu;
   7:  import android.view.View;
   8:  import android.widget.Button;
   9:  import android.widget.TextView;
  10:  ?
  11:  public class MainActivity extends Activity 
  12:  ?
  13:      Button btnCallWcf;
  14:      TextView txtMsg;
  15:      @Override
  16:      protected void onCreate(Bundle savedInstanceState) 
  17:          super.onCreate(savedInstanceState);
  18:          setContentView(R.layout.activity_main);
  19:          
  20:          btnCallWcf=(Button)this.findViewById(R.id.btnCallWcf);
  21:          txtMsg=(TextView)this.findViewById(R.id.txtMsg);
  22:          
  23:          btnCallWcf.setOnClickListener(WcfCall);
  24:      
  25:      
  26:      private Button.OnClickListener WcfCall=new Button.OnClickListener()
  27:  ?
  28:          @Override
  29:          public void onClick(View arg0) 
  30:              runOnUiThread(new Runnable() 
  31:                  @Override
  32:                  public void run() 
  33:                      try
  34:                          String wsURL="http://xxx.xxx.xxx.xxx:905/basicHttpSoapHeader.host/MyProducts.svc?singleWsdl";
  35:                          String soapAction="http://tempuri.org/IProductService/SaySomething";
  36:                          StringBuilder soapBody=new StringBuilder();
  37:                          soapBody.append("n");
  38:                          soapBody.append("  n");
  39:                          soapBody.append("    testmann");
  40:                          soapBody.append("    a123456n");
  41:                          soapBody.append("  n");
  42:                          soapBody.append("  n");
  43:                          soapBody.append("    n");
  44:                          soapBody.append("      中文 &amp; english 测试n");
  45:                          soapBody.append("    n");
  46:                          soapBody.append("  n"); 
  47:                          soapBody.append("n");
  48:                          
  49:                          SoapObject client=new SoapObject();
  50:                          client.setWsURL(wsURL);
  51:                          client.setSoapAction(soapAction);
  52:                          client.setSoapBody(soapBody.toString());
  53:                          
  54:                          txtMsg.setText(client.sendRequest());
  55:                          Log.v("success", txtMsg.getText().toString());
  56:                          catch(Exception er)
  57:                              Log.d("MAIN err", er.getMessage());
  58:                          
  59:                      
  60:                  
  61:              );
  62:              
  63:          
  64:          
  65:      ;
  66:  ?
  67:  

执行的结果

技术图片

有了这些做法﹐应该可以应付很多状况了。

原文:大专栏  WCF安全性认证:SoapHeader(二)使用HTTP Request调用


以上是关于WCF安全性认证:SoapHeader使用HTTP Request调用的主要内容,如果未能解决你的问题,请参考以下文章

项目中使用WCF替换asmx Web service总结

CXF 入门:创建一个基于SOAPHeader的安全验证(CXF拦截器使用)

以WCF安全认证方式调用通用权限管理系统获取基础信息资料

Restful风格wcf调用4——权限认证

ASP.NET Web Service 标准SOAP开发案例代码(自定义验证安全头SOAPHeader)

在 wcf 中添加用于安全身份验证的自定义标头