勇哥注:
此系列文章是梳理一下勇哥认为项目有用的WCF的知识点,读者须有WCF的开发经验。
wcf的安全机制
分为消息级与线路级
1。所有的wcf服务,不要使用证书(SSL证书,用于传输上的加密),证书很贵划不来
证书一个域名4K。
如果是 IOS下的webapi,是必须要证书的。
2。非证书使用方式
如果你的wcf需要对外,那么增加验证是必须的。
(1)如果对方是C#程序,可以在client和service端在header中增加参数再使用消息拦截,
【head] 中加用户名与密码
这样两边不需要额外代码
(图1)
如上图所示,我们在第一个Endpoint中置入用户名密码,在第二个endpoint取得用户名密码,如果不对,则拒绝访问。
java程序,使用用户名和密码,获取token,以后每个接口中都传输一个token参数进去。
(图2)
(2)如果对方是非C#程序,可以使用一个登陆接口,获取token参数后,client在以后每个调用中都需要传递token参数。
演示程序:
演示图1。
MyEndpointBehavior
using System; using System.Collections.Generic; using System.Linq; using System.ServiceModel.Channels; using System.ServiceModel.Description; using System.ServiceModel.Dispatcher; using System.Text; using System.Threading.Tasks; namespace Lib { public class MyEndpointBehavior : IEndpointBehavior { public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters) { throw new NotImplementedException(); } /// <summary> /// 这个是client实现的 /// </summary> /// <param name="endpoint"></param> /// <param name="clientRuntime"></param> public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime) { clientRuntime.ClientMessageInspectors.Add(new MyClientMessageInspector()); } /// <summary> /// 这个是service端实现的 /// </summary> /// <param name="endpoint"></param> /// <param name="endpointDispatcher"></param> public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher) { endpointDispatcher.DispatchRuntime.MessageInspectors.Add(new MyDispatchMessageInspector()); } public void Validate(ServiceEndpoint endpoint) { throw new NotImplementedException(); } } }
MyClientMessageInspector.cs
using System; using System.Collections.Generic; using System.Linq; using System.ServiceModel; using System.ServiceModel.Channels; using System.ServiceModel.Dispatcher; using System.Text; using System.Threading.Tasks; namespace Lib { public class MyClientMessageInspector : IClientMessageInspector { /// <summary> /// 发送之后 /// </summary> /// <param name="reply"></param> /// <param name="correlationState"></param> public void AfterReceiveReply(ref Message reply, object correlationState) { throw new NotImplementedException(); } /// <summary> /// 发送之前 /// </summary> /// <param name="request"></param> /// <param name="channel"></param> /// <returns></returns> public object BeforeSendRequest(ref Message request, IClientChannel channel) { var username = "samsun"; var password = "123"; request.Headers.Add(MessageHeader.CreateHeader("username", "", username)); request.Headers.Add(MessageHeader.CreateHeader("password", "", password)); return request; } } }
MyDispatchMessageInspector.cs
using System; using System.Collections.Generic; using System.Linq; using System.ServiceModel; using System.ServiceModel.Channels; using System.ServiceModel.Dispatcher; using System.Text; using System.Threading.Tasks; namespace Lib { public class MyDispatchMessageInspector : IDispatchMessageInspector { public object AfterReceiveRequest(ref Message request, IClientChannel channel, InstanceContext instanceContext) { //request.Headers.Add(MessageHeader.CreateHeader("username", "", username)); //request.Headers.Add(MessageHeader.CreateHeader("password", "", password)); var username= request.Headers.GetHeader<string>("username",""); var password = request.Headers.GetHeader<string>("password", ""); if (username == "samsun" && password == "123") { return request; } throw new Exception("用户名或者密码错误"); } public void BeforeSendReply(ref Message reply, object correlationState) { throw new NotImplementedException(); } } }
Client
using Contracts; using Lib; using System; using System.Collections.Generic; using System.Linq; using System.ServiceModel; using System.Text; using System.Threading.Tasks; namespace Client { class Program { static void Main(string[] args) { //using (ChannelFactory<ICalculator> channelFactory = new ChannelFactory<ICalculator>("calculatorservice")) //{ // //省略代码 // ICalculator proxy = channelFactory.CreateChannel(); // using (proxy as IDisposable) // { // proxy.DoWorker("hello world"); // Console.ReadKey(); // } //} ServiceReference1.CalculatorServiceClient client = new Client.ServiceReference1.CalculatorServiceClient(); client.Endpoint.EndpointBehaviors.Add(new MyEndpointBehavior()); try { client.DoWorker("Hello world"); } catch(Exception ex) { Console.WriteLine(ex.Message); } Console.ReadKey(); } } }
host:
using System.ServiceModel; using System.Text; using System.Threading.Tasks; namespace Hosting { class Program { static void Main(string[] args) { using (ServiceHost host = new ServiceHost(typeof(CalculatorService))) { host.Description.Endpoints[0].EndpointBehaviors.Add(new MyEndpointBehavior()); host.Opened += delegate { Console.WriteLine("CalculaorService已经启动,按任意键终止服务!"); }; host.Open(); Console.Read(); } } }
wcf的负载均横
www.cnblogs.com/huangxincheng/p/7707830.html

