[索引页]
[源码下载]
作者: 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"
/>
密码:
<
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
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
[源码下载]
[源码下载]
化零为整WCF(17) - 安全(Security)
作者: webabcd
介绍
WCF(Windows Communication Foundation) - 安全(Security):本文以用户名和密码做验证,通过X.509证书做加密为例
示例
1、证书
setup.bat


2、服务
IHello.cs

























Hello.cs


























CustomNamePasswordValidator.cs





























3、宿主
Hello.svc

Web.config


















































4、客户端
Hello.aspx
























Hello.aspx.cs















































Web.config




















































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