我使用this示例项目作为起点,但将其修改为使用HTTPS和TransportWithMessageCredential。
我正在通过启用了SSL的IIS Express运行服务器并且项目正在运行。
我有点不确定的是SSL证书,因为我必须将客户端设置为接受所有证书才能工作。
服务器配置:
<?xml version="1.0"?>
<configuration>
<system.web>
<compilation debug="true" targetFramework="4.5" />
<httpRuntime targetFramework="4.5" />
</system.web>
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior name="Behavior1">
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="false" />
<serviceCredentials>
<serviceCertificate findValue="MyWebSite"
storeLocation="LocalMachine"
storeName="My"
x509FindType="FindBySubjectName" />
<userNameAuthentication userNamePasswordValidationMode="Custom" customUserNamePasswordValidatorType="Service.UserNamePassValidator, Service" />
</serviceCredentials>
</behavior>
</serviceBehaviors>
</behaviors>
<bindings>
<wsHttpBinding>
<binding name="Binding1">
<security mode="TransportWithMessageCredential">
<transport clientCredentialType="Certificate" />
<message clientCredentialType="UserName"/>
</security>
</binding>
</wsHttpBinding>
</bindings>
<services>
<service behaviorConfiguration="Behavior1" name="Service.Service">
<endpoint address="" binding="wsHttpBinding" bindingConfiguration="Binding1" contract="Service.IService" />
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
<host>
<baseAddresses>
<add baseAddress="https://localhost/" />
</baseAddresses>
</host>
</service>
</services>
</system.serviceModel>
</configuration>
客户端配置:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.serviceModel>
<bindings>
<wsHttpBinding>
<binding name="WSHttpBinding_IService">
<security mode="TransportWithMessageCredential">
<message clientCredentialType="UserName" />
</security>
</binding>
</wsHttpBinding>
</bindings>
<client>
<endpoint address="https://localhost:44303/UsernamePasswordService.svc"
binding="wsHttpBinding" bindingConfiguration="WSHttpBinding_IService"
contract="ServiceReference1.IService" name="WSHttpBinding_IService" />
</client>
</system.serviceModel>
</configuration>
客户代码:
private void button1_Click(object sender, EventArgs e)
{
string time = "";
var c = new ServiceClient();
c.ClientCredentials.UserName.UserName = txtUser.Text;
c.ClientCredentials.UserName.Password = txtPassword.Text;
c.ClientCredentials.ServiceCertificate.Authentication.CertificateValidationMode = X509CertificateValidationMode.None;
ServicePointManager.ServerCertificateValidationCallback += RemoteCertificateValidate;
try
{
time = c.GetServertime();
MessageBox.Show(time, "You are authenticated");
}
catch (Exception ex)
{
if (ex.InnerException != null)
MessageBox.Show(ex.InnerException.Message, "Incorrect username/password");
else
MessageBox.Show(ex.Message, "Unhandled exception");
}
}
private static bool RemoteCertificateValidate(object sender, X509Certificate cert, X509Chain chain, SslPolicyErrors error)
{
// trust any certificate
return true;
}
从客户端代码中可以看出,所有证书都在RemoteCertificateValidate()中受信任。我发现这是在开发时解决自签名证书的一个例子。
我不明白为什么要设置
CertificateValidationMode = X509CertificateValidationMode.None;
不会产生同样的效果。这不能设置客户端不验证证书吗?
由于我还不了解SSL证书的分发方式,我有点不确定的是当我们获得有效的SSL证书时这是如何工作的。证书是否必须安装在所有客户端上?
我还尝试将流量从客户端记录到服务器,并在其中一条消息中注意到以下内容:
<o:Username>
<!-- Removed-->
</o:Username>
<o:Password>
<!-- Removed-->
</o:Password>
这是否意味着用户名和密码是以明文形式发送的?