WCF客户端证书和用户名凭据被禁止

Ros*_*ied 2 c# security wcf client-certificates

我在让WCF客户端连接到需要客户端证书和用户名/密码的服务器时遇到问题.

我已经验证使用JUST客户端证书使用此方法:

        var binding = new WSHttpBinding(SecurityMode.Transport);
        binding.Security.Transport = new HttpTransportSecurity();
        binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Certificate;

        var ea = new EndpointAddress(EndpointUrl);

        using (var p = new ServiceReference1.AAAClient(binding, ea))
        {
            try
            {
                p.ClientCredentials.ClientCertificate.SetCertificate(
                        System.Security.Cryptography.X509Certificates.StoreLocation.CurrentUser,
                        System.Security.Cryptography.X509Certificates.StoreName.My,
                        System.Security.Cryptography.X509Certificates.X509FindType.FindBySubjectName,
                        CertificateSubject);

                var x = p.RequiresClientCertificateOnly();
                Console.WriteLine("Status: " + x.status);
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.ToString());
            }

            Console.WriteLine();
        }
Run Code Online (Sandbox Code Playgroud)

下一个合乎逻辑的步骤是添加用户名/密码部分,但它会在未经授权的情况下返回403.我知道凭证和证书是有效的,因为我在中间使用fiddler提供客户端证书和用户名/密码,它工作正常,只是当通过WCF使用它似乎无法工作,或使用发送两个客户端证书和用户名/密码.

尝试使用两者的代码如下(尝试使用WSHttpBinding和BasicHttpBinding - 两者的结果相同):

        var binding = new BasicHttpBinding(BasicHttpSecurityMode.TransportWithMessageCredential);
        binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Certificate;
        binding.Security.Message.ClientCredentialType = BasicHttpMessageCredentialType.UserName;

        var ea = new EndpointAddress(EndpointUrl);

        using (var p = new ServiceReference1.PingPortTypeClient(binding, ea))
        {
            try
            {
                p.ClientCredentials.ClientCertificate.SetCertificate(
                        System.Security.Cryptography.X509Certificates.StoreLocation.CurrentUser,
                        System.Security.Cryptography.X509Certificates.StoreName.My,
                        System.Security.Cryptography.X509Certificates.X509FindType.FindBySubjectName,
                        CertificateSubject);

                p.ClientCredentials.UserName.UserName = Username;
                p.ClientCredentials.UserName.Password = Password;

                var x = p.pingDatabase();
                Console.WriteLine("Status: " + x.status);
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.ToString());
            }

            Console.WriteLine();
Run Code Online (Sandbox Code Playgroud)

当我直接在浏览器中转到URL时 - 我收到错误:

HTTP错误403.7 - 禁止您尝试访问的页面要求您的浏览器具有Web服务器可识别的安全套接字层(SSL)客户端证书.

这表明在上面的第二个例子中没有发送证书,因为它正在接收相同的错误(403).

有人可以帮我配置WCF以提供客户端证书和用户名/密码吗?我已经在网上搜索了,这里的"类似问题"根本没有帮助.现在变得非常沮丧 - 我错过了什么?

Yar*_*veh 5

如果您同时需要用户名(消息级别)和证书(传输级别),则必须使用自定义绑定.例如:

        <customBinding>
            <binding name="NewBinding0">
                <textMessageEncoding messageVersion="Default" />
                <security authenticationMode="UserNameOverTransport">
                    <secureConversationBootstrap />
                </security>
                <httpsTransport requireClientCertificate="true" />
            </binding>
        </customBinding>
Run Code Online (Sandbox Code Playgroud)

messageVersion的值取决于您是否要使用WSHttp或BasicHttp.目前我已将其设置为"Default",即WSHttp,对于Basic,将其设置为"Soap11".