【问题标题】:WCF https with only server certificate仅具有服务器证书的 WCF https
【发布时间】:2012-11-26 10:35:33
【问题描述】:

我尝试使用自签名证书进行 WCF。我找到了一些解决方案,但他们需要客户端在连接之前知道 clinet 证书。 我想让客户端作为浏览器工作(当浏览器使用 Web 服务器证书时)。 我的意思是浏览器在连接之前不知道网络服务器的证书,它可以从网络服务器获取它。 我的服务器的 web.config:

<system.serviceModel>
    <serviceHostingEnvironment aspNetCompatibilityEnabled="false" />
    <services>
      <service behaviorConfiguration="security" name="WebApplicationExchange.UKService">
        <endpoint address="" binding="basicHttpBinding" bindingConfiguration="security" contract="WebApplicationExchange.IUKService">
          <identity>
            <dns value="localhost" />
          </identity>
        </endpoint>
        <endpoint address="mex" binding="mexHttpsBinding" contract="IMetadataExchange" />
        <host>
          <baseAddresses>
            <add baseAddress="https://localhost/UKService/UKService.svc" />
          </baseAddresses>
        </host>
      </service>
    </services>
    <behaviors>
      <serviceBehaviors>
        <behavior name="security">
          <serviceMetadata httpGetEnabled="false" httpsGetEnabled="true" />
          <serviceCredentials>
            <userNameAuthentication userNamePasswordValidationMode="Custom" customUserNamePasswordValidatorType="ServiceAuthorization.PasswordValidator,ServiceAuthorization" />
            <windowsAuthentication allowAnonymousLogons="false" />
          </serviceCredentials>
          <serviceAuthorization principalPermissionMode="Custom">
            <authorizationPolicies>
              <add policyType="ServiceAuthorization.AuthorizationPolicy,ServiceAuthorization" />
            </authorizationPolicies>
          </serviceAuthorization>
          <serviceDebug includeExceptionDetailInFaults="true" />
        </behavior>
      </serviceBehaviors>
    </behaviors>
    <bindings>
      <basicHttpBinding>
        <binding name="security">
          <security mode="TransportWithMessageCredential">
            <transport clientCredentialType="Basic" />
          </security>
        </binding>
      </basicHttpBinding>
    </bindings>
  </system.serviceModel>

它适用于网络浏览器。

但客户端显示错误: 无法为具有权限“localhost:56389”的安全通道 SSL/TLS 建立信任连接。 客户端代码:

System.ServiceModel.EndpointAddress eaSecurity = new System.ServiceModel.EndpointAddress("https://localhost:56389/UKService.svc");
                var binding = new System.ServiceModel.BasicHttpBinding();
                binding.Security.Mode = System.ServiceModel.BasicHttpSecurityMode.TransportWithMessageCredential;
                binding.Security.Transport.ClientCredentialType = System.ServiceModel.HttpClientCredentialType.None;
                binding.Security.Message.ClientCredentialType = System.ServiceModel.BasicHttpMessageCredentialType.UserName;


                var securityFactory = new System.ServiceModel.ChannelFactory<ServiceReference1.IUKService>(binding, eaSecurity);
                securityFactory.Credentials.UserName.UserName = "test";
                securityFactory.Credentials.UserName.Password = "test";
                myService = securityFactory.CreateChannel();

有什么办法解决这个问题吗?

更新: 我深入查看错误堆栈并发现以下内容: System.Security.Authentication.AuthenticationException:根据身份验证结果,远程证书无效。 我试过这段代码:

  ClientCredentials cc = securityFactory.Endpoint.Behaviors.Find<ClientCredentials>();

                cc.UserName.UserName = "test";
                cc.UserName.Password = "test";

               cc.ServiceCertificate.Authentication.CertificateValidationMode = X509CertificateValidationMode.None;

但这并没有帮助。

【问题讨论】:

  • 浏览器通过让人工手动验证证书来做到这一点。这就是你想要做的吗?
  • 不完全是,我的意思是浏览器在连接之前不知道网络服务器的证书,它可以从网络服务器获取它。
  • 正确,但这仅在使用浏览器的人已经有足够的信息来验证证书时才有用。您是否打算使用人工干预?还是您已经有足够的信息来验证证书?
  • 我更喜欢不验证证书。我在更新中编写了代码。但是错误是一样的

标签: c# wcf https


【解决方案1】:

我是这样解决的:

System.Net.ServicePointManager.ServerCertificateValidationCallback += new System.Net.Security.RemoteCertificateValidationCallback(RemoteCertValidateCallback);
 public static bool RemoteCertValidateCallback(object sender, X509Certificate cert, X509Chain chain, System.Net.Security.SslPolicyErrors error)
        {
            return true;
        }

【讨论】:

    【解决方案2】:

    问题是客户端不信任您的证书。这与客户端证书或从浏览器下载证书无关。

    为了让客户端接受服务器证书,您需要:

    • 从受信任的证书颁发机构购买证书
    • 将证书(或其根)添加到客户端计算机的证书存储区或
    • 禁用证书验证。

    【讨论】:

    • 禁用证书验证 - 它适合我。我写了以下代码:ClientCredentials cc = securityFactory.Endpoint.Behaviors.Find(); cc.UserName.UserName = "测试"; cc.UserName.Password = "测试"; cc.ServiceCertificate.Authentication.CertificateValidationMode = X509CertificateValidationMode.None;
    • 但这无济于事。错误是一样的
    猜你喜欢
    • 2012-12-11
    • 1970-01-01
    • 1970-01-01
    • 2015-05-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-08-06
    • 2013-12-03
    相关资源
    最近更新 更多