WCF Client Certificate AND UserName Credentials forbidden

纵然是瞬间 提交于 2019-12-23 00:51:23

问题


I'm having issues getting a WCF client to connect to a server that requires a client certificate and also a username / password.

I have verified that using JUST the client certificate works using this:

        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();
        }

The next logical step was to add the username / password parts, but it comes back with 403 unauthorised. I know the credentials and the certificate are valid as I have used fiddler in the middle to provide the client certificate and username / password and it works fine, just when using all through WCF it doesnt seem to work, or use send both the client certificate and the username / password.

The code trying to use both is below (tried with WSHttpBinding and BasicHttpBinding - same result for both):

        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();

When I goto the URL directly in a browser - I get the error:

HTTP Error 403.7 - Forbidden The page you are attempting to access requires your browser to have a Secure Sockets Layer (SSL) client certificate that the Web server recognizes.

This to suggests that the certificate is not being sent in the second example above as it is the same error (403) being received.

Can someone please help me with the configuration for WCF to provide the client certificate AND the username / password? I have trawled the web, and the 'similar questions' on here have not helped at all. Getting very frustrate by it now - what am i missing?


回答1:


You have to use a custom binding if you want both username (message level) and certificate (transport level). For example:

        <customBinding>
            <binding name="NewBinding0">
                <textMessageEncoding messageVersion="Default" />
                <security authenticationMode="UserNameOverTransport">
                    <secureConversationBootstrap />
                </security>
                <httpsTransport requireClientCertificate="true" />
            </binding>
        </customBinding>

The value of messageVersion depends if you want to use WSHttp or BasicHttp. Currently I've set it to "Default" which is WSHttp, for Basic set it to "Soap11".



来源:https://stackoverflow.com/questions/18247924/wcf-client-certificate-and-username-credentials-forbidden

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!