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

简介:
[索引页]
[源码下载] 


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


作者: webabcd


介绍
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
InBlock.gif using System; 
InBlock.gif using System.Collections.Generic; 
InBlock.gif using System.Linq; 
InBlock.gif using System.Text; 
InBlock.gif 
InBlock.gif using System.ServiceModel; 
InBlock.gif 
InBlock.gif namespace WCF.ServiceLib.Security 
InBlock.gif
InBlock.gif         /// <summary> 
InBlock.gif         /// IHello接口 
InBlock.gif         /// </summary> 
InBlock.gif        [ServiceContract] 
InBlock.gif         public  interface IHello 
InBlock.gif        { 
InBlock.gif                 /// <summary> 
InBlock.gif                 /// 打招呼方法 
InBlock.gif                 /// </summary> 
InBlock.gif                 /// <param name="name">人名</param> 
InBlock.gif                 /// <returns></returns> 
InBlock.gif                [OperationContract] 
InBlock.gif                 string SayHello( string name); 
InBlock.gif        } 
InBlock.gif}
 
Hello.cs
InBlock.gif using System; 
InBlock.gif using System.Collections.Generic; 
InBlock.gif using System.Linq; 
InBlock.gif using System.Text; 
InBlock.gif 
InBlock.gif using System.ServiceModel; 
InBlock.gif 
InBlock.gif namespace WCF.ServiceLib.Security 
InBlock.gif
InBlock.gif         /// <summary> 
InBlock.gif         /// Hello类 
InBlock.gif         /// </summary> 
InBlock.gif         public  class Hello : IHello 
InBlock.gif        { 
InBlock.gif                 /// <summary> 
InBlock.gif                 /// 打招呼方法 
InBlock.gif                 /// </summary> 
InBlock.gif                 /// <param name="name">人名</param> 
InBlock.gif                 /// <returns></returns> 
InBlock.gif                 public  string SayHello( string name) 
InBlock.gif                { 
InBlock.gif                         return  "Hello: " + name; 
InBlock.gif                } 
InBlock.gif        } 
InBlock.gif}
 
CustomNamePasswordValidator.cs
InBlock.gif using System; 
InBlock.gif using System.Collections.Generic; 
InBlock.gif using System.Linq; 
InBlock.gif using System.Text; 
InBlock.gif 
InBlock.gif using System.ServiceModel; 
InBlock.gif 
InBlock.gif namespace WCF.ServiceLib.Security 
InBlock.gif
InBlock.gif         /// <summary> 
InBlock.gif         /// 自定义的用户名/密码验证类 
InBlock.gif         /// </summary> 
InBlock.gif         public  class CustomNamePasswordValidator : System.IdentityModel.Selectors.UserNamePasswordValidator 
InBlock.gif        { 
InBlock.gif                 /// <summary> 
InBlock.gif                 /// 验证指定的用户名和密码 
InBlock.gif                 /// </summary> 
InBlock.gif                 /// <param name="userName">要验证的用户名</param> 
InBlock.gif                 /// <param name="password">要验证的密码</param> 
InBlock.gif                 public  override  void Validate( string userName,  string password) 
InBlock.gif                { 
InBlock.gif                         if (!(userName ==  "webabcd" && password ==  "webabcd")) 
InBlock.gif                        { 
InBlock.gif                                 throw  new FaultException( "用户名或密码不正确"); 
InBlock.gif                        } 
InBlock.gif                } 
InBlock.gif        } 
InBlock.gif}
 
 
3、宿主
Hello.svc
<%@ ServiceHost Language="C#" Debug="true" Service="WCF.ServiceLib.Security.Hello" %>
 
Web.config
<?xml version="1.0"?> 
<configuration> 
        <system.serviceModel> 
                <services> 
                        <!--name - 提供服务的类名--> 
                        <!--behaviorConfiguration - 指定相关的行为配置--> 
                        <service name="WCF.ServiceLib.Security.Hello" behaviorConfiguration="SecurityBehavior"> 
                                <!--address - 服务地址--> 
                                <!--binding - 通信方式--> 
                                <!--contract - 服务契约--> 
                                <endpoint address="" binding="wsHttpBinding" contract="WCF.ServiceLib.Security.IHello" bindingConfiguration="SecurityBindingConfiguration"    /> 
                        </service> 
                </services> 
                <behaviors> 
                        <serviceBehaviors> 
                                <behavior name="SecurityBehavior"> 
                                        <!--httpGetEnabled - 指示是否发布服务元数据以便使用 HTTP/GET 请求进行检索,如果发布 WSDL,则为 true,否则为 false,默认值为 false--> 
                                        <serviceMetadata httpGetEnabled="true" /> 
                                        <serviceDebug includeExceptionDetailInFaults="true"/> 
                                        <serviceCredentials> 
                                                <!--userNamePasswordValidationMode - 以用户名/密码模式来进行验证的方法--> 
                                                <!--UserNamePasswordValidationMode.Windows - 用户名映射到 Windows 用户--> 
                                                <!--UserNamePasswordValidationMode.MembershipProvider - 提供基于已配置的 MembershipProvider 的密码验证--> 
                                                <!--UserNamePasswordValidationMode.Custom - 基于已配置的自定义 UsernamePasswordValidator 的自定义身份验证--> 
                                                <!--customUserNamePasswordValidatorType - 所使用的自定义用户名密码验证程序的类型--> 
                                                <userNameAuthentication userNamePasswordValidationMode="Custom" customUserNamePasswordValidatorType="WCF.ServiceLib.Security.CustomNamePasswordValidator, WCF.ServiceLib" /> 
                                                <!--findValue - 指定要在 X.509 证书存储区中搜索的值--> 
                                                <!--storeLocation - 指定客户端可用于验证服务器证书的证书存储区位置(LocalMachine - 分配给本地计算机的 X.509 证书存储区;CurrentUser - 当前用户使用的 X.509 证书存储区)--> 
                                                <!--storeName - 要打开的 X.509 证书存储区的名称(参看:StoreName枚举。AddressBook, AuthRoot, CertificateAuthority, Disallowed, My, Root, TrustedPeople, TrustedPublisher)--> 
                                                <!--x509FindType - 要执行的 X.509 搜索的类型(参看:X509FindType枚举)--> 
                                                <serviceCertificate findValue="Webabcd" storeLocation="LocalMachine" storeName="My" x509FindType="FindBySubjectName" /> 
                                        </serviceCredentials> 
                                </behavior> 
                        </serviceBehaviors> 
                </behaviors> 
                <bindings> 
                        <wsHttpBinding> 
                                <binding name="SecurityBindingConfiguration"> 
                                        <security> 
                                                <!--clientCredentialType - 客户端用以进行身份验证的凭据的类型,默认值 UserName --> 
                                                <!--BasicHttpMessageCredentialType.UserName - 使用用户名凭据对客户端进行身份验证--> 
                                                <!--BasicHttpMessageCredentialType.Certificate - 使用证书对客户端进行身份验证--> 
                                                <message clientCredentialType="UserName" /> 
                                        </security> 
                                </binding> 
                        </wsHttpBinding> 
                </bindings> 
        </system.serviceModel> 
</configuration>
 
 
4、客户端
Hello.aspx
<%@ Page Language="C#" MasterPageFile="~/Site.master" AutoEventWireup="true" CodeFile="Hello.aspx.cs" 
        Inherits="Sample_Security" Title="安全(Security)" %> 

<asp:Content ID="Content1" ContentPlaceHolderID="head" runat="Server"> 
</asp:Content> 
<asp:Content ID="Content2" ContentPlaceHolderID="ContentPlaceHolder1" runat="Server"> 
        <p> 
                以用户名和密码做验证,通过X.509证书做加密为例 
        </p> 
        <p> 
                <asp:Label ID="lblMsg" runat="server" /> 
        </p> 
        <p> 
                用户名:<asp:TextBox ID="txtUserName" runat="server" Text="webabcd" /> 
                     
                密码:<asp:TextBox ID="txtPassword" runat="server" Text="webabcd" /> 
        </p> 
        <p> 
                <asp:TextBox ID="txtName" runat="server" Text="webabcd" /> 
                  
                <asp:Button ID="btnSayHello" runat="server" Text="Hello" OnClick="btnSayHello_Click" /> 
        </p> 
</asp:Content>
 
Hello.aspx.cs
InBlock.gif using System; 
InBlock.gif using System.Collections; 
InBlock.gif using System.Configuration; 
InBlock.gif using System.Data; 
InBlock.gif using System.Linq; 
InBlock.gif using System.Web; 
InBlock.gif using System.Web.Security; 
InBlock.gif using System.Web.UI; 
InBlock.gif using System.Web.UI.HtmlControls; 
InBlock.gif using System.Web.UI.WebControls; 
InBlock.gif using System.Web.UI.WebControls.WebParts; 
InBlock.gif using System.Xml.Linq; 
InBlock.gif 
InBlock.gif public partial  class Sample_Security : System.Web.UI.Page 
InBlock.gif
InBlock.gif         protected  void Page_Load( object sender, EventArgs e) 
InBlock.gif        { 
InBlock.gif 
InBlock.gif        } 
InBlock.gif 
InBlock.gif         protected  void btnSayHello_Click( object sender, EventArgs e) 
InBlock.gif        { 
InBlock.gif                 using (var proxy =  new SecuritySvc.HelloClient()) 
InBlock.gif                { 
InBlock.gif                         try 
InBlock.gif                        { 
InBlock.gif                                 // proxy.ClientCredentials.ServiceCertificate.Authentication.CertificateValidationMode = System.ServiceModel.Security.X509CertificateValidationMode.PeerTrust; 
InBlock.gif 
InBlock.gif                                proxy.ClientCredentials.UserName.UserName = txtUserName.Text; 
InBlock.gif                                proxy.ClientCredentials.UserName.Password = txtPassword.Text; 
InBlock.gif 
InBlock.gif                                lblMsg.Text = proxy.SayHello(txtName.Text); 
InBlock.gif                        } 
InBlock.gif                         catch (TimeoutException ex) 
InBlock.gif                        { 
InBlock.gif                                lblMsg.Text = ex.ToString(); 
InBlock.gif                                proxy.Abort(); 
InBlock.gif                        } 
InBlock.gif                         catch (Exception ex) 
InBlock.gif                        { 
InBlock.gif                                lblMsg.Text = ex.ToString(); 
InBlock.gif                                proxy.Abort(); 
InBlock.gif                        } 
InBlock.gif                } 
InBlock.gif        } 
InBlock.gif}
 
Web.config
<?xml version="1.0"?> 
<configuration> 
        <system.serviceModel> 
                <client> 
                        <!--address - 服务地址--> 
                        <!--binding - 通信方式--> 
                        <!--contract - 服务契约--> 
                        <!--bindingConfiguration - 指定相关的绑定配置--> 
                        <!--behaviorConfiguration - 指定相关的行为配置--> 
                        <endpoint address="http://localhost:3502/ServiceHost/Security/Hello.svc" 
                                binding="wsHttpBinding" 
                                contract="SecuritySvc.IHello" 
                                bindingConfiguration="HelloBindingConfiguration" 
                                behaviorConfiguration="HelloBehaviorConfiguration"> 
                                <identity> 
                                        <!--encodedValue - 此证书编码的值。公钥,用于加密用户名和密码。测试时,请根据实际情况修改此值--> 
                                        <certificate encodedValue="AwAAAAEAAAAUAAAAwMJESjc9Bbgeh9hIrrdrlMz0nfEgAAAAAQAAALMBAAAwggGvMIIBXaADAgECAhBC+dqPonX5pEwDPMLbdE9MMAkGBSsOAwIdBQAwFjEUMBIGA1UEAxMLUm9vdCBBZ2VuY3kwHhcNMDgwNzE1MDczODIwWhcNMzkxMjMxMjM1OTU5WjASMRAwDgYDVQQDEwdXZWJhYmNkMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCwfrBPcMSOWVJmDnn+EFfCOslH0OqC5s67C6e19XQ7oMh6a9hP9Os4hefNoGxcdPK3orV4y4pHn0VOvHgaeAJqreRjmgmyb+h2BDB7nkmhchBxQZUx4jSX0GUrqECZm9uUMrNq8vx7NtaEuEMs5q50KPaxrv6PwuKLssNnb3WC1wIDAQABo0swSTBHBgNVHQEEQDA+gBAS5AktBh0dTwCNYSHcFmRjoRgwFjEUMBIGA1UEAxMLUm9vdCBBZ2VuY3mCEAY3bACqAGSKEc+41KpcNfQwCQYFKw4DAh0FAANBAE/6rAQhU3X1RficEHPEeUAX7HQQXZDYByQt0QqE7C8PaViQWlWU+Sp8u9Oy3ce4DSg3wgQLL/DIknG7FMIiGRE=" /> 
                                </identity> 
                        </endpoint> 
                </client> 
                <bindings> 
                        <wsHttpBinding> 
                                <binding name="HelloBindingConfiguration"> 
                                        <security> 
                                                <!--clientCredentialType - 客户端用以进行身份验证的凭据的类型,默认值 UserName --> 
                                                <!--BasicHttpMessageCredentialType.UserName - 使用用户名凭据对客户端进行身份验证--> 
                                                <!--BasicHttpMessageCredentialType.Certificate - 使用证书对客户端进行身份验证--> 
                                                <message clientCredentialType="UserName" /> 
                                        </security> 
                                </binding> 
                        </wsHttpBinding> 
                </bindings> 
                <behaviors> 
                        <endpointBehaviors> 
                                <behavior name="HelloBehaviorConfiguration"> 
                                        <clientCredentials> 
                                                <serviceCertificate> 
                                                        <!--authentication - 证书验证模式 --> 
                                                        <!--X509CertificateValidationMode.None - 不使用证书验证--> 
                                                        <!--X509CertificateValidationMode.PeerTrust - 如果证书位于被信任的人的存储区中,则有效--> 
                                                        <!--X509CertificateValidationMode.ChainTrust - 如果该链在受信任的根存储区生成证书颁发机构,则证书有效--> 
                                                        <!--X509CertificateValidationMode.PeerOrChainTrust -如果证书位于被信任的人的存储区或该链在受信任的根存储区生成证书颁发机构,则证书有效 --> 
                                                        <!--X509CertificateValidationMode.Custom -用户必须插入自定义 X509CertificateValidator 以验证证书 --> 
                                                        <authentication certificateValidationMode="PeerTrust" /> 
                                                </serviceCertificate> 
                                        </clientCredentials> 
                                </behavior> 
                        </endpointBehaviors> 
                </behaviors> 
        </system.serviceModel> 
</configuration>
 
 

运行结果:
单击"btnSayHello"按钮,显示"Hello: webabcd"。经过加密的用户名和密码放在SOAP头中传输。


OK
[源码下载]


     本文转自webabcd 51CTO博客,原文链接: http://blog.51cto.com/webabcd/344171 ,如需转载请自行联系原作者

相关文章
|
安全 网络协议 网络安全
WCF安全3-Transport与Message安全模式
WCF安全3-Transport与Message安全模式
112 0
WCF安全3-Transport与Message安全模式
|
存储 算法 安全
WCF安全2-非对称加密
WCF安全2-非对称加密
139 0
WCF安全2-非对称加密
|
安全 数据安全/隐私保护
WCF安全1-开篇
WCF安全1-开篇
109 0
WCF安全1-开篇
|
安全 数据安全/隐私保护