化零为整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
using  System;
using  System.Collections.Generic;
using  System.Linq;
using  System.Text;

using  System.ServiceModel;

namespace  WCF.ServiceLib.Security
{
    
/// <summary>
    
/// IHello接口
    
/// </summary>

    [ServiceContract]
    
public interface IHello
    
{
        
/// <summary>
        
/// 打招呼方法
        
/// </summary>
        
/// <param name="name">人名</param>
        
/// <returns></returns>

        [OperationContract]
        
string SayHello(string name);
    }

}


Hello.cs
using  System;
using  System.Collections.Generic;
using  System.Linq;
using  System.Text;

using  System.ServiceModel;

namespace  WCF.ServiceLib.Security
{
    
/// <summary>
    
/// Hello类
    
/// </summary>

    public class Hello : IHello
    
{
        
/// <summary>
        
/// 打招呼方法
        
/// </summary>
        
/// <param name="name">人名</param>
        
/// <returns></returns>

        public string SayHello(string name)
        
{
            
return "Hello: " + name;
        }

    }

}


CustomNamePasswordValidator.cs
using  System;
using  System.Collections.Generic;
using  System.Linq;
using  System.Text;

using  System.ServiceModel;

namespace  WCF.ServiceLib.Security
{
    
/// <summary>
    
/// 自定义的用户名/密码验证类
    
/// </summary>

    public class CustomNamePasswordValidator : System.IdentityModel.Selectors.UserNamePasswordValidator
    
{
        
/// <summary>
        
/// 验证指定的用户名和密码
        
/// </summary>
        
/// <param name="userName">要验证的用户名</param>
        
/// <param name="password">要验证的密码</param>

        public override void Validate(string userName, string password)
        
{
            
if (!(userName == "webabcd" && password == "webabcd"))
            
{
                
throw new FaultException("用户名或密码不正确");
            }

        }

    }

}



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"   />
        
&nbsp;  
        密码:
< asp:TextBox  ID ="txtPassword"  runat ="server"  Text ="webabcd"   />
    
</ p >
    
< p >
        
< asp:TextBox  ID ="txtName"  runat ="server"  Text ="webabcd"   />
        
&nbsp;
        
< asp:Button  ID ="btnSayHello"  runat ="server"  Text ="Hello"  OnClick ="btnSayHello_Click"   />
    
</ p >
</ asp:Content >

Hello.aspx.cs
using  System;
using  System.Collections;
using  System.Configuration;
using  System.Data;
using  System.Linq;
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)
            
{
                lblMsg.Text 
= ex.ToString();
                proxy.Abort();
            }

        }

    }

}


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
[源码下载]

你可能感兴趣的:(Security)