1. 程式人生 > >WCF雙工通訊+身份認證

WCF雙工通訊+身份認證

證書

  以管理員身份開啟VS開發人員命令提示符工具 然後輸入如下字串   makecert -sr localmachine -ssRoot -n CN=GreenWhale -sky exchange -pe -r。 回車返回Success即可。 然後開啟“C:\Windows\System32\en-US\certlm.msc”  Zh-CN也可 “C:\Windows\System32\zh-CN\certlm.msc 別打錯了是這個“certmgr.msc” 然後就可以看到證書了,匯出證書,軟體釋出後讓客戶端安裝此證書即可。

服務端

 服務端回撥介面:

using
System.ServiceModel; using System.Net; namespace WcfService1 { publicinterfaceIServerCallClient     {
        [OperationContract] IPEndPointServerRequestClientIP();
        [OperationContract] voidServerSayMsg(string text);     } }

服務介面

usingSystem; usingSystem.ServiceModel; namespaceWcfService1
{     [ServiceContract(CallbackContract=typeof(IServerCallClient))] publicinterfaceIClientCallServer     {         [OperationContract] voidClientSayToServer(string text);         [OperationContract] DateTimeClientRequestDateTime();     } }

WCF 服務端程式碼實現

請注意,服務端回撥客戶端時 客戶端的連結必須沒有斷開,斷開了就無法回調了,

usingSystem; usingSystem.Collections.Generic; usingSystem.Diagnostics; usingSystem.IO; usingSystem.Linq; usingSystem.Net; usingSystem.Runtime.Serialization; usingSystem.ServiceModel; usingSystem.ServiceModel.Web; usingSystem.Text; usingSystem.Timers; namespaceWcfService1 { // 注意: 使用“重構”選單上的“重新命名”命令,可以同時更改程式碼、svc 和配置檔案中的類名“Service1”。 // 注意: 為了啟動 WCF 測試客戶端以測試此服務,請在解決方案資源管理器中選擇 Service1.svc 或 Service1.svc.cs,然後開始除錯。     [ServiceBehavior(InstanceContextMode=InstanceContextMode.Single)] publicclassClientCallServer :IClientCallServer,IDisposable     { Timer timer=newTimer(); publicClientCallServer()         { timer.Elapsed+=Timer_Elapsed; timer.Interval=5000; timer.Start();         } privatevoidTimer_Elapsed(object sender,ElapsedEventArgs e)         { if (ServerCallClient!=null)             { foreach (var iteminServerCallClient)                 { item.ServerSayMsg("SB");                 }             }         } publicstaticList<IServerCallClient> ServerCallClient=newList<IServerCallClient>(); publicDateTimeClientRequestDateTime()         { returnDateTime.Now;         } publicvoidClientSayToServer(string text)         { var channel=OperationContext.Current.GetCallbackChannel<IServerCallClient>(); ServerCallClient.Add(channel); Debug.WriteLine(OperationContext.Current.SessionId); Debug.WriteLine(text);         } publicvoidDispose()         { ServerCallClient.Clear();         }     } }

身份認證

實現身份認證需要服務端繼承System.IdentityModel.Selectors.UserNamePasswordValidator類。同理需要引用System.IdentityModel.Dll;

namespaceWcfService1 { /// <summary> /// WCF身份認證 /// </summary> publicclassWCFValidator : System.IdentityModel.Selectors.UserNamePasswordValidator     { /// <summary> /// 身份及密碼驗證 /// </summary> /// <paramname="userName"></param> /// <paramname="password"></param> publicoverridevoid Validate(string userName,string password)         { if (userName=="1234"&&password=="1234")//身份驗證不過則報錯,過了就過了。             {             } else             { thrownewSystem.IdentityModel.Tokens.SecurityTokenException("Unknown Username or Password");             }         }     } }

Web配置檔案

<?xml version="1.0" encoding="utf-8"?> <configuration> <system.web> <compilationdebug="true"targetFramework="4.0"/> </system.web> <system.serviceModel> <services> <servicename="WcfService1.ClientCallServer"> <endpointaddress=""binding="wsDualHttpBinding"bindingConfiguration="NewBinding0" contract="WcfService1.IClientCallServer"> </endpoint> </service> </services> <bindings> <wsDualHttpBinding> <bindingname="NewBinding0"> <securitymode="Message"><--訊息加密-> <messageclientCredentialType="UserName"/> </security> </binding> </wsDualHttpBinding> </bindings> <behaviors> <serviceBehaviors> <behavior> <serviceCredentials> <--findValue 公司名稱=GreenWhale,storeLocation==儲存位置本機,儲存位置:Root(根證書區)-> <serviceCertificatefindValue="CN=GreenWhale"x509FindType="FindBySubjectDistinguishedName"storeLocation="LocalMachine"storeName="Root"></serviceCertificate> <clientCertificate> <authenticationcertificateValidationMode="None"></authentication> </clientCertificate> <---customUserNamePasswordValidatorType,先放動態庫的名稱空間+類名,然後時逗號然後是dll名稱,我這裡時WcfService1---> <userNameAuthenticationuserNamePasswordValidationMode="Custom"includeWindowsGroups="false"customUserNamePasswordValidatorType="WcfService1.WCFValidator,WcfService1"></userNameAuthentication> </serviceCredentials> <!-- 為避免洩漏元資料資訊,請在部署前將以下值設定為 false --> <serviceMetadatahttpGetEnabled="true"/> <!-- 要接收故障異常詳細資訊以進行除錯,請將以下值設定為 true。在部署前設定為 false 以避免洩漏異常資訊 --> <serviceDebugincludeExceptionDetailInFaults="false"/> </behavior> </serviceBehaviors> </behaviors> <serviceHostingEnvironmentaspNetCompatibilityEnabled="false" multipleSiteBindingsEnabled="true"/> </system.serviceModel> <system.webServer> <modulesrunAllManagedModulesForAllRequests="true"/> <!--         若要在除錯過程中瀏覽 Web 應用程式根目錄,請將下面的值設定為 True。         在部署之前將該值設定為 False 可避免洩露 Web 應用程式資料夾資訊。       --> <directoryBrowseenabled="true"/> </system.webServer> </configuration>

客戶端

客戶端很簡單,首先引用WCF服務,然後在連線時輸入對應的賬號和密碼即可。

usingSystem; usingSystem.Collections.Generic; usingSystem.ComponentModel; usingSystem.Data; usingSystem.Drawing; usingSystem.Linq; usingSystem.Net; usingSystem.ServiceModel; usingSystem.Text; usingSystem.Windows.Forms; usingSystem.Xml; usingWindowsFormsApp1.Service; namespaceWindowsFormsApp1 { publicpartialclass Form1 :Form, IClientCallServerCallback     { publicForm1()         { InitializeComponent(); context=newInstanceContext(this); client=newClientCallServerClient(context);         } publicIPEndPointServerRequestClientIP()         { thrownewNotImplementedException();         } InstanceContext context; publicvoidServerSayMsg(string text)         { MessageBox.Show(text);         } ClientCallServerClient client; privatevoidbutton1_Click(object sender,EventArgs e)         { //  certificateValidationMode client.ClientCredentials.UserName.UserName="1234"; client.ClientCredentials.UserName.Password="1234"; client.ClientSayToServer("Fuck");         }     } }