天天看點

化零為整WCF(17) - 安全(Security)

<a href="http://webabcd.blog.51cto.com/1787395/343999" target="_blank">[索引頁]</a>

化零為整WCF(17) - 安全(Security)

介紹

WCF(Windows Communication Foundation) - 安全(Security):本文以使用者名和密碼做驗證,通過X.509證書做加密為例

示例

1、證書

setup.bat

makecert -sr LocalMachine -ss My -a sha1 -n CN=Webabcd -sky exchange -pe 

certmgr -add -r LocalMachine -s My -c -n Webabcd -s TrustedPeople

2、服務

IHello.cs

using System; 

using System.Collections.Generic; 

using System.Linq; 

using System.Text; 

using System.ServiceModel; 

namespace WCF.ServiceLib.Security 

        /// &lt;summary&gt; 

        /// IHello接口 

        /// &lt;/summary&gt; 

        [ServiceContract] 

        public interface IHello 

        { 

                /// &lt;summary&gt; 

                /// 打招呼方法 

                /// &lt;/summary&gt; 

                /// &lt;param name="name"&gt;人名&lt;/param&gt; 

                /// &lt;returns&gt;&lt;/returns&gt; 

                [OperationContract] 

                string SayHello(string name); 

        } 

}

Hello.cs

        /// Hello類 

        public class Hello : IHello 

                public string SayHello(string name) 

                { 

                        return "Hello: " + name; 

                } 

CustomNamePasswordValidator.cs

        /// 自定義的使用者名/密碼驗證類 

        public class CustomNamePasswordValidator : System.IdentityModel.Selectors.UserNamePasswordValidator 

                /// 驗證指定的使用者名和密碼 

                /// &lt;param name="userName"&gt;要驗證的使用者名&lt;/param&gt; 

                /// &lt;param name="password"&gt;要驗證的密碼&lt;/param&gt; 

                public override void Validate(string userName, string password) 

                        if (!(userName == "webabcd" &amp;&amp; password == "webabcd")) 

                        { 

                                throw new FaultException("使用者名或密碼不正确"); 

                        } 

3、宿主

Hello.svc

&lt;%@ ServiceHost Language="C#" Debug="true" Service="WCF.ServiceLib.Security.Hello" %&gt;

Web.config

&lt;?xml version="1.0"?&gt; 

&lt;configuration&gt; 

        &lt;system.serviceModel&gt; 

                &lt;services&gt; 

                        &lt;!--name - 提供服務的類名--&gt; 

                        &lt;!--behaviorConfiguration - 指定相關的行為配置--&gt; 

                        &lt;service name="WCF.ServiceLib.Security.Hello" behaviorConfiguration="SecurityBehavior"&gt; 

                                &lt;!--address - 服務位址--&gt; 

                                &lt;!--binding - 通信方式--&gt; 

                                &lt;!--contract - 服務契約--&gt; 

                                &lt;endpoint address="" binding="wsHttpBinding" contract="WCF.ServiceLib.Security.IHello" bindingConfiguration="SecurityBindingConfiguration"    /&gt; 

                        &lt;/service&gt; 

                &lt;/services&gt; 

                &lt;behaviors&gt; 

                        &lt;serviceBehaviors&gt; 

                                &lt;behavior name="SecurityBehavior"&gt; 

                                        &lt;!--httpGetEnabled - 訓示是否釋出服務中繼資料以便使用 HTTP/GET 請求進行檢索,如果釋出 WSDL,則為 true,否則為 false,預設值為 false--&gt; 

                                        &lt;serviceMetadata httpGetEnabled="true" /&gt; 

                                        &lt;serviceDebug includeExceptionDetailInFaults="true"/&gt; 

                                        &lt;serviceCredentials&gt; 

                                                &lt;!--userNamePasswordValidationMode - 以使用者名/密碼模式來進行驗證的方法--&gt; 

                                                &lt;!--UserNamePasswordValidationMode.Windows - 使用者名映射到 Windows 使用者--&gt; 

                                                &lt;!--UserNamePasswordValidationMode.MembershipProvider - 提供基于已配置的 MembershipProvider 的密碼驗證--&gt; 

                                                &lt;!--UserNamePasswordValidationMode.Custom - 基于已配置的自定義 UsernamePasswordValidator 的自定義身份驗證--&gt; 

                                                &lt;!--customUserNamePasswordValidatorType - 所使用的自定義使用者名密碼驗證程式的類型--&gt; 

                                                &lt;userNameAuthentication userNamePasswordValidationMode="Custom" customUserNamePasswordValidatorType="WCF.ServiceLib.Security.CustomNamePasswordValidator, WCF.ServiceLib" /&gt; 

                                                &lt;!--findValue - 指定要在 X.509 證書存儲區中搜尋的值--&gt; 

                                                &lt;!--storeLocation - 指定用戶端可用于驗證伺服器證書的證書存儲區位置(LocalMachine - 配置設定給本地計算機的 X.509 證書存儲區;CurrentUser - 目前使用者使用的 X.509 證書存儲區)--&gt; 

                                                &lt;!--storeName - 要打開的 X.509 證書存儲區的名稱(參看:StoreName枚舉。AddressBook, AuthRoot, CertificateAuthority, Disallowed, My, Root, TrustedPeople, TrustedPublisher)--&gt; 

                                                &lt;!--x509FindType - 要執行的 X.509 搜尋的類型(參看:X509FindType枚舉)--&gt; 

                                                &lt;serviceCertificate findValue="Webabcd" storeLocation="LocalMachine" storeName="My" x509FindType="FindBySubjectName" /&gt; 

                                        &lt;/serviceCredentials&gt; 

                                &lt;/behavior&gt; 

                        &lt;/serviceBehaviors&gt; 

                &lt;/behaviors&gt; 

                &lt;bindings&gt; 

                        &lt;wsHttpBinding&gt; 

                                &lt;binding name="SecurityBindingConfiguration"&gt; 

                                        &lt;security&gt; 

                                                &lt;!--clientCredentialType - 用戶端用以進行身份驗證的憑據的類型,預設值 UserName --&gt; 

                                                &lt;!--BasicHttpMessageCredentialType.UserName - 使用使用者名憑據對用戶端進行身份驗證--&gt; 

                                                &lt;!--BasicHttpMessageCredentialType.Certificate - 使用證書對用戶端進行身份驗證--&gt; 

                                                &lt;message clientCredentialType="UserName" /&gt; 

                                        &lt;/security&gt; 

                                &lt;/binding&gt; 

                        &lt;/wsHttpBinding&gt; 

                &lt;/bindings&gt; 

        &lt;/system.serviceModel&gt; 

&lt;/configuration&gt;

4、用戶端

Hello.aspx

&lt;%@ Page Language="C#" MasterPageFile="~/Site.master" AutoEventWireup="true" CodeFile="Hello.aspx.cs" 

        Inherits="Sample_Security" Title="安全(Security)" %&gt; 

&lt;asp:Content ID="Content1" ContentPlaceHolderID="head" runat="Server"&gt; 

&lt;/asp:Content&gt; 

&lt;asp:Content ID="Content2" ContentPlaceHolderID="ContentPlaceHolder1" runat="Server"&gt; 

        &lt;p&gt; 

                以使用者名和密碼做驗證,通過X.509證書做加密為例 

        &lt;/p&gt; 

                &lt;asp:Label ID="lblMsg" runat="server" /&gt; 

                使用者名:&lt;asp:TextBox ID="txtUserName" runat="server" Text="webabcd" /&gt; 

                密碼:&lt;asp:TextBox ID="txtPassword" runat="server" Text="webabcd" /&gt; 

                &lt;asp:TextBox ID="txtName" runat="server" Text="webabcd" /&gt; 

                &lt;asp:Button ID="btnSayHello" runat="server" Text="Hello" OnClick="btnSayHello_Click" /&gt; 

&lt;/asp:Content&gt;

Hello.aspx.cs

using System.Collections; 

using System.Configuration; 

using System.Data; 

using System.Web; 

using System.Web.Security; 

using System.Web.UI; 

using System.Web.UI.HtmlControls; 

using System.Web.UI.WebControls; 

using System.Web.UI.WebControls.WebParts; 

using System.Xml.Linq; 

public partial class Sample_Security : System.Web.UI.Page 

        protected void Page_Load(object sender, EventArgs e) 

        protected void btnSayHello_Click(object sender, EventArgs e) 

                using (var proxy = new SecuritySvc.HelloClient()) 

                        try 

                                // proxy.ClientCredentials.ServiceCertificate.Authentication.CertificateValidationMode = System.ServiceModel.Security.X509CertificateValidationMode.PeerTrust; 

                                proxy.ClientCredentials.UserName.UserName = txtUserName.Text; 

                                proxy.ClientCredentials.UserName.Password = txtPassword.Text; 

                                lblMsg.Text = proxy.SayHello(txtName.Text); 

                        catch (TimeoutException ex) 

                                lblMsg.Text = ex.ToString(); 

                                proxy.Abort(); 

                        catch (Exception ex) 

                &lt;client&gt; 

                        &lt;!--address - 服務位址--&gt; 

                        &lt;!--binding - 通信方式--&gt; 

                        &lt;!--contract - 服務契約--&gt; 

                        &lt;!--bindingConfiguration - 指定相關的綁定配置--&gt; 

                        &lt;endpoint address="http://localhost:3502/ServiceHost/Security/Hello.svc" 

                                binding="wsHttpBinding" 

                                contract="SecuritySvc.IHello" 

                                bindingConfiguration="HelloBindingConfiguration" 

                                behaviorConfiguration="HelloBehaviorConfiguration"&gt; 

                                &lt;identity&gt; 

                                        &lt;!--encodedValue - 此證書編碼的值。公鑰,用于加密使用者名和密碼。測試時,請根據實際情況修改此值--&gt; 

                                        &lt;certificate encodedValue="AwAAAAEAAAAUAAAAwMJESjc9Bbgeh9hIrrdrlMz0nfEgAAAAAQAAALMBAAAwggGvMIIBXaADAgECAhBC+dqPonX5pEwDPMLbdE9MMAkGBSsOAwIdBQAwFjEUMBIGA1UEAxMLUm9vdCBBZ2VuY3kwHhcNMDgwNzE1MDczODIwWhcNMzkxMjMxMjM1OTU5WjASMRAwDgYDVQQDEwdXZWJhYmNkMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCwfrBPcMSOWVJmDnn+EFfCOslH0OqC5s67C6e19XQ7oMh6a9hP9Os4hefNoGxcdPK3orV4y4pHn0VOvHgaeAJqreRjmgmyb+h2BDB7nkmhchBxQZUx4jSX0GUrqECZm9uUMrNq8vx7NtaEuEMs5q50KPaxrv6PwuKLssNnb3WC1wIDAQABo0swSTBHBgNVHQEEQDA+gBAS5AktBh0dTwCNYSHcFmRjoRgwFjEUMBIGA1UEAxMLUm9vdCBBZ2VuY3mCEAY3bACqAGSKEc+41KpcNfQwCQYFKw4DAh0FAANBAE/6rAQhU3X1RficEHPEeUAX7HQQXZDYByQt0QqE7C8PaViQWlWU+Sp8u9Oy3ce4DSg3wgQLL/DIknG7FMIiGRE=" /&gt; 

                                &lt;/identity&gt; 

                        &lt;/endpoint&gt; 

                &lt;/client&gt; 

                                &lt;binding name="HelloBindingConfiguration"&gt; 

                        &lt;endpointBehaviors&gt; 

                                &lt;behavior name="HelloBehaviorConfiguration"&gt; 

                                        &lt;clientCredentials&gt; 

                                                &lt;serviceCertificate&gt; 

                                                        &lt;!--authentication - 證書驗證模式 --&gt; 

                                                        &lt;!--X509CertificateValidationMode.None - 不使用證書驗證--&gt; 

                                                        &lt;!--X509CertificateValidationMode.PeerTrust - 如果證書位于被信任的人的存儲區中,則有效--&gt; 

                                                        &lt;!--X509CertificateValidationMode.ChainTrust - 如果該鍊在受信任的根存儲區生成證書頒發機構,則證書有效--&gt; 

                                                        &lt;!--X509CertificateValidationMode.PeerOrChainTrust -如果證書位于被信任的人的存儲區或該鍊在受信任的根存儲區生成證書頒發機構,則證書有效 --&gt; 

                                                        &lt;!--X509CertificateValidationMode.Custom -使用者必須插入自定義 X509CertificateValidator 以驗證證書 --&gt; 

                                                        &lt;authentication certificateValidationMode="PeerTrust" /&gt; 

                                                &lt;/serviceCertificate&gt; 

                                        &lt;/clientCredentials&gt; 

                        &lt;/endpointBehaviors&gt; 

運作結果:

單擊"btnSayHello"按鈕,顯示"Hello: webabcd"。經過加密的使用者名和密碼放在SOAP頭中傳輸。

OK

<a href="http://down.51cto.com/data/100781" target="_blank">[源碼下載下傳]</a>

     本文轉自webabcd 51CTO部落格,原文連結:http://blog.51cto.com/webabcd/344171,如需轉載請自行聯系原作者