學會WCF之試錯法——安全配置報錯分析
阿新 • • 發佈:2022-05-03
服務端配置
<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);
}
服務端和客戶端配置如上。wsHttpBinding的Message安全模式,客戶端憑據預設為Windows
執行客戶端,丟擲異常:
丟擲異常的原因是,Transport模式支援HTTPS,TCP,ICP,MSMQ,而這裡終結點地址是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安全模式(本機除錯)
wsHttpBinding的Message安全模式,客戶端憑據預設為Windows。
服務地址配置為https://localhost/S,服務端與客戶端安全模式相同
<security mode="Message">
<transport clientCredentialType="Windows"></transport>
</security>
執行客戶端,丟擲異常
丟擲異常的原因是,wsHttpBinding的Message安全模式不支援https協議,改為http協議則正常。
但是,當服務端的客戶端憑據配置與客戶端不一致時,也可以正常執行,並獲得正常的結果。
例如,服務端配置:
<security mode="Message">
<transport clientCredentialType="Basic"></transport>
</security>
客戶端配置:
<security mode="Message">
<transport clientCredentialType="Windows"></transport>
</security>
-----------------------------------------------------------------------------------------
時間倉促,水平有限,如有不當之處,歡迎指正。