簡體   English   中英

WCF 客戶端證書和用戶名憑據被禁止

[英]WCF Client Certificate AND UserName Credentials forbidden

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

下一個合乎邏輯的步驟是添加用戶名/密碼部分,但它返回 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();

當我直接在瀏覽器中轉到 URL 時 - 我收到錯誤消息:

HTTP 錯誤 403.7 - 禁止 您嘗試訪問的頁面要求您的瀏覽器具有 Web 服務器可識別的安全套接字層 (SSL) 客戶端證書。

這表明在上面的第二個示例中沒有發送證書,因為它收到了相同的錯誤 (403)。

有人可以幫我配置 WCF 以提供客戶端證書和用戶名/密碼嗎? 我瀏覽了網絡,這里的“類似問題”根本沒有幫助。 現在變得非常沮喪 - 我錯過了什么?

如果您需要用戶名(消息級別)和證書(傳輸級別),則必須使用自定義綁定。 例如:

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

messageVersion 的值取決於您是要使用 WSHttp 還是 BasicHttp。 目前我已將其設置為“默認”,即 WSHttp,對於 Basic,將其設置為“Soap11”。

傳輸級別的用戶名和證書

不是這個問題的答案,但問題標題把我帶到了這里,所以也許其他人也有:
我需要一個 Soap11 綁定,同時具有證書(對於網關)和傳輸級別(對於應用程序)的用戶名。 (這兩個部件都由客戶現場的不同團隊和不同供應商維護。)

盡管名稱為帶有UserNameOverTransportcustomBinding在 Soap-header(消息級別)中發送用戶名和密碼,而不是在 http-header(傳輸級別)中,導致SecurityRequestChannel.ProcessReply此內部FaultException源自應用程序:

FaultException: MustUnderstand headers: [{http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd}Security] are not understood.

basicHttpBinding<security mode="TransportCredentialOnly">會導致:

The provided URI scheme 'https' is invalid; expected 'http'.
Parameter name: via

經過大量的反復試驗,結果證明這可以通過組合配置和代碼來完成。

通過配置傳輸的證書示例

  <basicHttpBinding>
    <binding name="myBasicHttpBindingForTransportCertificate">
      <security mode="Transport">
        <transport clientCredentialType="Certificate" />
      </security>
    </binding>
  </basicHttpBinding>

  <endpointBehaviors>
    <behavior name="myCertificateBehavior">
      <clientCredentials>
        <clientCertificate findValue="my certificate subject" x509FindType="FindBySubjectName" storeLocation="LocalMachine" storeName="My" />
      </clientCredentials>
    </behavior>

(我使用這個答案動態加載了它。)

通過代碼傳輸的用戶名和密碼示例

using (new OperationContextScope(client.InnerChannel))
{
    …
    var httpRequestProperty = new HttpRequestMessageProperty();
    httpRequestProperty.Headers[System.Net.HttpRequestHeader.Authorization] =
           "Basic " + Convert.ToBase64String(System.Text.Encoding.ASCII.GetBytes($"{username}:{password}"));
    OperationContext.Current.OutgoingMessageProperties[HttpRequestMessageProperty.Name] = httpRequestProperty;

(感謝這個對“WCF TransportCredentialOnly 不發送用戶名和密碼”的舊回答。)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM