1. 程式人生 > >學會WCF之試錯法——安全配置報錯分析

學會WCF之試錯法——安全配置報錯分析

request length ntc ron add cat deb 執行 異常

安全配置報錯分析

服務端配置

<system.serviceModel>
     <bindings>
      <wsHttpBinding>
        <binding name ="WsHttpBinding_IService" maxReceivedMessageSize="370000" receiveTimeout="00:10:01" maxBufferPoolSize="100">
          <readerQuotas maxStringContentLength="240000"/>
          <security 
mode="Transport"> <transport clientCredentialType="Windows"></transport> </security> </binding> </wsHttpBinding> </bindings> <services> <service name="WCF_Find_Error_Lib.Service" behaviorConfiguration="beh">
<endpoint address="" binding="wsHttpBinding" contract="WCF_Find_Error_Lib.IService" bindingConfiguration="WsHttpBinding_IService"> </endpoint> <host> <baseAddresses> <add
baseAddress="http://localhost/S" /> </baseAddresses> </host> </service> </services> <behaviors> <serviceBehaviors> <behavior name="beh"> <serviceThrottling maxConcurrentCalls="1"/> <serviceMetadata httpGetEnabled="True" httpsGetEnabled="True" httpGetUrl="http://localhost/S"/> <serviceDebug includeExceptionDetailInFaults="True" /> </behavior> </serviceBehaviors> </behaviors> </system.serviceModel>

服務契約

[ServiceContract]
    public interface IService
    {
        [OperationContract]
        string GetData(int value);

        [OperationContract]
        string GetString(string value);

        [OperationContract]
        void Upload(Request request);
    }

    [MessageContract]
    public class Request
    {
        [MessageHeader(MustUnderstand = true)]
        public string FileName { get; set; }

        [MessageBodyMember(Order = 1)]
        public Stream Content {get;set;}
}

服務

[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession, ConcurrencyMode = ConcurrencyMode.Reentrant)]
    public class Service : IService
    {
        public string GetData(int value)
        {
            //Thread.Sleep(120000);
            return string.Format("You entered: {0}", value);
        }

        public string GetString(string value)
        {
            //Thread.Sleep(120000);
            Thread.Sleep(5000);
            return string.Format("You entered: {0}", value);
        }

        public void Upload(Request request)
        {
            try
            {
                StreamReader sr = new StreamReader(request.Content, Encoding.GetEncoding("GB2312"));
                StreamWriter sw = new StreamWriter("E:\\" + request.FileName + ".txt", false, Encoding.GetEncoding("GB2312"));
                while (!sr.EndOfStream)
                {
                    sw.WriteLine(sr.ReadLine());
                    Thread.Sleep(5000);
                }
                sr.Close();
                sw.Close();
            }
            catch (Exception ex)
            { }
            
        }
  }

服務寄宿

  class Program
    {
        static void Main(string[] args)
        {
            try
            {
                ServiceHost host = new ServiceHost(typeof(Service));
                host.Open();
                Console.WriteLine("服務狀態:"+host.State.ToString());
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
            

            Console.WriteLine("服務啟動");
            Console.WriteLine("按任意鍵停止服務");
            Console.ReadLine();
        }
  }

客戶端配置

<system.serviceModel>
    <bindings>
      <wsHttpBinding>
        <binding name ="WsHttpBinding_IService" maxReceivedMessageSize="370000" receiveTimeout="00:10:01" maxBufferPoolSize="100">
          <readerQuotas maxStringContentLength="240000"/>
          <security mode="Transport">
            <transport clientCredentialType="Windows">
            </transport>
          </security>
        </binding>
      </wsHttpBinding>
    </bindings>
    <client>
      <endpoint address="http://localhost/S" binding="wsHttpBinding"
          bindingConfiguration="WsHttpBinding_IService" contract="IService"
          name="WHttpBinding_IService" />
    </client>
  </system.serviceModel>

客戶端代理

  public class ServiceProxy
    {
        public string GetData(int value)
        {
            string ret = null;
            ServiceClient client = null;
            try
            {
                client = new ServiceClient();
                ret = client.GetData(value);
                client.Close();
            }
            catch
            {
                if (client != null)
                {
                    client.Abort();
                }
                throw;
            }
            return ret;
        }

        public string GetString(string value)
        {
            string ret = null;
            ServiceClient client = null;
            try
            {
                client = new ServiceClient();
                ret = client.GetString(value);
                client.Close();
            }
            catch
            {
                if (client != null)
                {
                    client.Abort();
                }
                throw;
            }
            return ret;
        }
        public void Upload(Request request)
        {
            ServiceClient client = null;
            try
            {
                client = new ServiceClient();
                client.Upload(request);
                client.Close();
            }
            catch
            {
                if (client != null)
                {
                    client.Abort();
                }
                throw;
            }
        }

    }


    [ServiceContractAttribute(ConfigurationName = "IService")]
    public interface IService
    {

        [System.ServiceModel.OperationContractAttribute(Action = "http://tempuri.org/IService/GetData", ReplyAction = "http://tempuri.org/IService/GetDataResponse")]
        string GetData(int value);

        [System.ServiceModel.OperationContractAttribute(Action = "http://tempuri.org/IService/GetString", ReplyAction = "http://tempuri.org/IService/GetStringResponse")]
        string GetString(string value);

        [System.ServiceModel.OperationContractAttribute(Action = "http://tempuri.org/IService/Upload", ReplyAction = "http://tempuri.org/IService/UploadResponse")]
        void Upload(Request request);
    }
    [MessageContract]
    public class Request
    {
        [MessageHeader(MustUnderstand = true)]
        public string FileName { get; set; }

        [MessageBodyMember(Order = 1)]
        public Stream Content { get; set; }
    }
    [ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall, ConcurrencyMode = ConcurrencyMode.Reentrant)]
    public class ServiceClient : System.ServiceModel.ClientBase<IService>, IService
    {

        public ServiceClient()
        {
        }

        public string GetData(int value)
        {
            return base.Channel.GetData(value);
        }

        public string GetString(string value)
        {
            return base.Channel.GetString(value);
        }

        public void Upload(Request request) 
        {
            base.Channel.Upload(request);
        }
  }

1 Transport安全模式(本機調試)

客戶端調用

using (ServiceClient client = new ServiceClient())
{
    StreamReader sr = new StreamReader("D:\\CSBMTEMP.txt", Encoding.Default);
    string str = sr.ReadToEnd();
    sr.Close();
    var s = client.GetString(str);
}

服務端和客戶端配置如上。wsHttpBindingMessage安全模式,客戶端憑據默認為Windows

運行客戶端,拋出異常:

技術分享圖片

拋出異常的原因是,Transport模式支持HTTPSTCPICPMSMQ,而這裏終結點地址是http://localhost/S,沒有使用HTTPS協議。將終結點地址改為https://localhost/S即可。

服務端和客戶端配置的安全模式不一樣時

服務端安全模式修改為:

<security mode="Transport">
       <transport clientCredentialType="Basic"></transport>
</security>

客戶端保持不變:

<security mode="Transport">
     <transport clientCredentialType="Windows"></transport>
</security>

運行客戶端,拋出異常:

技術分享圖片

將客戶端安全配置改為Basic,與服務端相同

<security mode="Transport">
            <transport clientCredentialType="Basic"></transport>
</security>

運行客戶端,拋出異常,因為Transport模式不支持Basic這種客戶端憑據。

技術分享圖片

2 Message安全模式(本機調試)

wsHttpBindingMessage安全模式,客戶端憑據默認為Windows

服務地址配置為https://localhost/S,服務端與客戶端安全模式相同

<security mode="Message">
     <transport clientCredentialType="Windows"></transport>
</security>

運行客戶端,拋出異常

技術分享圖片

拋出異常的原因是,wsHttpBindingMessage安全模式不支持https協議,改為http協議則正常。

但是,當服務端的客戶端憑據配置與客戶端不一致時,也可以正常執行,並獲得正常的結果。

例如,服務端配置:

<security mode="Message">
       <transport clientCredentialType="Basic"></transport>
</security>

客戶端配置:

<security mode="Message">
      <transport clientCredentialType="Windows"></transport>
</security>

學會WCF之試錯法——安全配置報錯分析