最近在配置WCF的时候,需要一点麻烦,避免以后才出现错误,特记录起来
1.wcf需要使用用户名和X509证书验证
A.服务器的config配置
a.bindings/binding中使用
<security mode="Message">
<transport clientCredentialType="Windows" />
<message clientCredentialType="UserName" />
</security>
说明: mode等于Message可以不用https方式。
b.service中 <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />中,需要确认binding是否为http
说明: http的binding为mexHttpBinding,而https的binding为mexHttpsBinding
c.behaviors/serviceBehaviors/behavior需要设置证书的位置
<serviceCertificate findValue="CnServer" storeLocation="LocalMachine"
x509FindType="FindBySubjectName" />
d.behaviors/serviceBehaviors/behavior需要设置使用的方式。 http就是使用 httpGetEnabled
<serviceMetadata httpGetEnabled="true" />
B.客户端的config配置
a.bindings/binding下面配置为
<security mode="Message">
<transport clientCredentialType="Windows" proxyCredentialType="None"
realm="" />
<message clientCredentialType="UserName" negotiateServiceCredential="true"
establishSecurityContext="true" />
</security>
b.如果你有一个真正的X509证书,那么现在的代码就可以正常运行了。但是很不幸,我们的证书是测试用的,我们运行的时候出错:'X.509 certificate CN=MyServerCert 链生成失败。所使用的证书具有无法验证的信任链。请替换该证书或更改 certificateValidationMode。已处理证书链,但是在不受信任提供程序信任的根证书中终止',WCF无法验证测试证书的信任链,那我们要做的就是绕过这个信任验证,具体做法如下
<behaviors>
<endpointBehaviors>
<behavior name="myClientBehavior">
<clientCredentials>
<serviceCertificate>
<authentication certificateValidationMode="Custom" customCertificateValidatorType="xxxxxx.MyX509Validator,xxxxx.TestApplication" />
</serviceCertificate>
</clientCredentials>
</behavior>
</endpointBehaviors>
</behaviors>
c.客户端代码增加
public class MyX509Validator : X509CertificateValidator {
/// <summary> /// Validates a certificate. /// </summary> /// <param name="certificate">The certificate the validate.</param> public override void Validate(X509Certificate2 certificate) { // validate argument //if (certificate == null) // throw new ArgumentNullException("X509认证证书为空!"); //// check if the name of the certifcate matches //if (certificate.SubjectName.Name != ConfigurationManager.AppSettings["CertName"]) // throw new SecurityTokenValidationException("Certificated was not issued by thrusted issuer"); return; }
}
2.wcf需要使用SSL及证书
A.服务器的config配置
a.bindings/binding中使用
<security mode="TransportWithMessageCredential">
<message clientCredentialType="UserName" />
</security>
说明: mode使用Transport,TransportWithMessageCredential必须是https方式。
b.service中 <endpoint address="mex" binding="mexHttpsBinding" contract="IMetadataExchange" />中,需要确认binding是否为https
说明: http的binding为mexHttpBinding,而https的binding为mexHttpsBinding
c.behaviors/serviceBehaviors/behavior需要设置证书的位置
<serviceCertificate findValue="CnServer" storeLocation="LocalMachine" x509FindType="FindBySubjectName" />
d.behaviors/serviceBehaviors/behavior需要设置使用的方式。 http就是使用 httpsGetEnabled
<serviceMetadata httpsGetEnabled="true" />
B.客户端的config配置
a.bindings/binding下面配置为
<security mode="TransportWithMessageCredential">
<transport clientCredentialType="None" proxyCredentialType="None"
realm="" />
<message clientCredentialType="UserName" negotiateServiceCredential="true"
algorithmSuite="Default" establishSecurityContext="true" />
</security>
b.如果你有一个真正的X509证书,那么现在的代码就可以正常运行了。但是很不幸,我们的证书是测试用的,我们运行的时候出错:'X.509 certificate CN=MyServerCert 链生成失败。所使用的证书具有无法验证的信任链。请替换该证书或更改 certificateValidationMode。已处理证书链,但是在不受信任提供程序信任的根证书中终止',WCF无法验证测试证书的信任链,那我们要做的就是绕过这个信任验证,具体做法如下
<behaviors> <endpointBehaviors> <behavior name="myClientBehavior"> <clientCredentials> <serviceCertificate> <authentication certificateValidationMode="Custom" customCertificateValidatorType="xxxxxx.MyX509Validator,xxxxx.TestApplication" /> </serviceCertificate> </clientCredentials> </behavior> </endpointBehaviors> </behaviors>
c.客户端代码增加
public class MyX509Validator : X509CertificateValidator {
/// <summary> /// Validates a certificate. /// </summary> /// <param name="certificate">The certificate the validate.</param> public override void Validate(X509Certificate2 certificate) { // validate argument //if (certificate == null) // throw new ArgumentNullException("X509认证证书为空!"); //// check if the name of the certifcate matches //if (certificate.SubjectName.Name != ConfigurationManager.AppSettings["CertName"]) // throw new SecurityTokenValidationException("Certificated was not issued by thrusted issuer"); return; }
}
d.客户端代码增加以下代码,在调用服务的时候,就先调用Util.SetCertificatePolicy();
public static class Util { /// <summary> /// Sets the cert policy. /// </summary> public static void SetCertificatePolicy() { ServicePointManager.ServerCertificateValidationCallback += RemoteCertificateValidate; }
/// <summary> /// Remotes the certificate validate. /// </summary> private static bool RemoteCertificateValidate( object sender, X509Certificate cert, X509Chain chain, SslPolicyErrors error) { // trust any certificate!!! System.Console.WriteLine("Warning, trust any certificate"); return true; } }