带有SSL证书的WCF服务器+用户名/密码和winforms客户端

时间:2013-12-19 11:58:49

标签: c# wcf ssl https wshttpbinding

我使用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>

这是否意味着用户名和密码是以明文形式发送的?

0 个答案:

没有答案