2016-08-16 25 views
7

ja napotykają następujący błąd podczas próby połączenia z WCF API, które jest za pomocą HTTPS Proxy:WCF WS2007FederationHttpBinding HTTPS

Certyfikat serwera o nazwie „CN = hostname” nie powiodło się, ponieważ jego weryfikacji tożsamości (”odcisk palca X ') nie jest zgodny z określonym w tożsamości punktu końcowego ("Y"). W wyniku tego bieżące żądanie HTTPS nie powiodło się. Zaktualizuj tożsamość punktu końcowego używaną na kliencie lub certyfikat używany przez serwer.

Gdzie X jest odcisk palca certyfikatu używanego przez serwer proxy i Y odcisk palca certyfikatu używanego przez usługę

Problemem jest to, że udało mi się dostać token z STS, ale nie mogę wykonać żadnej sieci wezwanie serwisowe po tym.

Powieliłem problem na moim komputerze za pomocą lokalnego serwera proxy SSL, certyfikat używany na serwerze proxy jest zaufany na moim komputerze. Wszystko działa poprawnie podczas korzystania z protokołu HTTP.

Szukałem rozwiązania dla kilku dni i zauważyłem ten artykuł KB który jest zbliżony do mojego problemu, ale nie dotyczy już (Biegnę próbkę i serwer w .NET 4.5): https://support.microsoft.com/en-us/kb/2564823

Co czy ja tęsknię?

Oto kod:

class Program 
{ 
    static void Main(string[] args) 
    { 
     Thread.CurrentThread.CurrentUICulture = new CultureInfo("en-us"); 

     string serverUrl = ConfigurationManager.AppSettings["ServerURL"]; 
     GenericXmlSecurityToken token = GetToken(serverUrl); 

     Console.WriteLine("Token Received"); 
     Console.WriteLine(token); 

     TestServiceClient client = CreateClient(serverUrl, token); 

     try 
     { 
      client.SearchSomething(); 

      Console.WriteLine("SearchSomething succeeded"); 
     } 
     catch (Exception e) 
     { 
      Console.WriteLine("SearchSomething failed :" + e); 
     } 

     Console.ReadLine(); 

    } 

    private static TestServiceClient CreateClient(string serverUrl, GenericXmlSecurityToken token) 
    { 
     var binding = new WS2007FederationHttpBinding(WSFederationHttpSecurityMode.Message) 
     { 
      MaxReceivedMessageSize = int.MaxValue, 
      MaxBufferPoolSize = int.MaxValue 
     }; 

     binding.Security.Message.EstablishSecurityContext = false; 
     binding.Security.Message.IssuedTokenType = "http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.1#SAMLV1.1"; 
     binding.Security.Message.NegotiateServiceCredential = false; 

     binding.ReaderQuotas.MaxDepth = int.MaxValue; 
     binding.ReaderQuotas.MaxStringContentLength = int.MaxValue; 
     binding.ReaderQuotas.MaxArrayLength = int.MaxValue; 
     binding.ReaderQuotas.MaxBytesPerRead = int.MaxValue; 
     binding.ReaderQuotas.MaxNameTableCharCount = int.MaxValue; 

     var uri = new Uri(serverUrl + "Test.Service/Test.Service.svc"); 

     var identity = new X509CertificateEndpointIdentity(new X509Certificate2(ConfigurationManager.AppSettings["ServiceCertificate"], ConfigurationManager.AppSettings["ServiceCertificatePassword"])); 

     var client = new TestServiceClient(binding, new EndpointAddress(uri, identity)); 
     client.ClientCredentials.SupportInteractive = false; 

     var customBinding = new CustomBinding(); 
     var bindingElements = binding.CreateBindingElements(); 

     if (serverUrl.Contains("https")) 
     { 
      bindingElements.Remove<HttpTransportBindingElement>(); 

      bindingElements.Add(new HttpsTransportBindingElement() { MaxReceivedMessageSize = int.MaxValue }); 
     } 
     customBinding.Elements.AddRange(bindingElements.ToArray()); 

     client.Endpoint.Binding = customBinding; 

     var clientCredentials = new SamlClientCredentials(token, client.ClientCredentials); 
     client.Endpoint.Behaviors.Remove<ClientCredentials>(); 
     client.Endpoint.Behaviors.Add(clientCredentials); 

     return client; 
    } 

    private static GenericXmlSecurityToken GetToken(string serverUrl) 
    { 
     string username = ConfigurationManager.AppSettings["Username"]; 
     string password = ConfigurationManager.AppSettings["Password"]; 
     string identityDnsName = ConfigurationManager.AppSettings["IdentityDnsName"]; 
     string ClientCertificate = ConfigurationManager.AppSettings["ClientCertificate"]; 
     string ClientCertificatePassword = ConfigurationManager.AppSettings["ClientCertificatePassword"]; 
     string ServiceCertificate = ConfigurationManager.AppSettings["ServiceCertificate"]; 
     string ServiceCertificatePassword = ConfigurationManager.AppSettings["ServiceCertificatePassword"]; 

     var stsUrl = serverUrl + "Security.Sts/Security.Sts.svc"; 

     GenericXmlSecurityToken token = null; 

     try 
     { 
      var customBinding = new CustomBinding(); 

      var securityBindingElement = 
       (SymmetricSecurityBindingElement) SecurityBindingElement.CreateMutualCertificateBindingElement(); 
      securityBindingElement.SetKeyDerivation(true); 
      securityBindingElement.MessageSecurityVersion = 
       MessageSecurityVersion 
        .WSSecurity11WSTrust13WSSecureConversation13WSSecurityPolicy12BasicSecurityProfile10; 
      securityBindingElement.MessageProtectionOrder = MessageProtectionOrder.SignBeforeEncrypt; 
      securityBindingElement.RequireSignatureConfirmation = false; 

      var securityTokenParameters = new UserNameSecurityTokenParameters() 
      { 
       InclusionMode = SecurityTokenInclusionMode.AlwaysToRecipient, 
       RequireDerivedKeys = false 
      }; 
      securityBindingElement.EndpointSupportingTokenParameters.SignedEncrypted.Add(securityTokenParameters); 
      customBinding.Elements.Add(securityBindingElement); 

      if (serverUrl.StartsWith("http:")) 
       customBinding.Elements.Add(new HttpTransportBindingElement() 
       { 
        MaxReceivedMessageSize = int.MaxValue, 
        MaxBufferPoolSize = int.MaxValue, 
        MaxBufferSize = int.MaxValue 
       }); 
      else if (serverUrl.StartsWith("https:")) 
       customBinding.Elements.Add(new HttpsTransportBindingElement() 
       { 
        MaxReceivedMessageSize = int.MaxValue, 
        MaxBufferPoolSize = int.MaxValue, 
        MaxBufferSize = int.MaxValue 
       }); 

      var stsChannelFactory = new WSTrustChannelFactory(customBinding, 
       new EndpointAddress(new Uri(stsUrl), new DnsEndpointIdentity(identityDnsName))); 

      stsChannelFactory.Credentials.SupportInteractive = false; 

      stsChannelFactory.Credentials.ClientCertificate.Certificate = new X509Certificate2(ClientCertificate, 
       ClientCertificatePassword); 
      stsChannelFactory.Credentials.ServiceCertificate.DefaultCertificate = 
       new X509Certificate2(ServiceCertificate, ServiceCertificatePassword); 
      stsChannelFactory.Credentials.ServiceCertificate.Authentication.CertificateValidationMode = 
       X509CertificateValidationMode.None; 

      stsChannelFactory.Credentials.UserName.UserName = username; 
      stsChannelFactory.Credentials.UserName.Password = password; 

      foreach (OperationDescription operationDescription in stsChannelFactory.Endpoint.Contract.Operations) 
      { 
       var operationBehavior = 
        operationDescription.Behaviors.Find<DataContractSerializerOperationBehavior>(); 
       if (operationBehavior != null) 
        operationBehavior.MaxItemsInObjectGraph = int.MaxValue; 
      } 

      var stsChannel = stsChannelFactory.CreateChannel(); 

      RequestSecurityToken request = new RequestSecurityToken(); 
      request.KeyType = "http://schemas.microsoft.com/idfx/keytype/symmetric"; 
      request.RequestType = "http://docs.oasis-open.org/ws-sx/ws-trust/200512/Issue"; 
      request.TokenType = "http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.1#SAMLV1.1"; 
      token = (GenericXmlSecurityToken) stsChannel.Issue(request); 

      return token; 
     } 
     catch (Exception e) 
     { 
      Console.WriteLine("GetToken Exception :" + e); 
     } 
     return token; 
    } 
} 

internal class SamlClientCredentials : ClientCredentials 
{ 
    public GenericXmlSecurityToken Token { get; private set; } 

    public SamlClientCredentials(GenericXmlSecurityToken token, ClientCredentials clientCredentials) 
     : base(clientCredentials) 
    { 
     Token = token; 
    } 

    protected override ClientCredentials CloneCore() 
    { 
     return new SamlClientCredentials(Token, this); 
    } 

    public override SecurityTokenManager CreateSecurityTokenManager() 
    { 
     return new SamlSecurityTokenManager(this); 
    } 
} 

internal class SamlSecurityTokenManager : ClientCredentialsSecurityTokenManager 
{ 
    private SamlClientCredentials clientCredentials; 

    public SamlSecurityTokenManager(SamlClientCredentials clientCredentials) 
     : base(clientCredentials) 
    { 
     this.clientCredentials = clientCredentials; 
    } 

    public override SecurityTokenProvider CreateSecurityTokenProvider(SecurityTokenRequirement tokenRequirement) 
    { 
     if (tokenRequirement.TokenType == SecurityTokenTypes.Saml || tokenRequirement.TokenType == "http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.1#SAMLV1.1") 
      return new SamlSecurityTokenProvider(this.clientCredentials.Token); 
     return base.CreateSecurityTokenProvider(tokenRequirement); 
    } 
} 

internal class SamlSecurityTokenProvider : SecurityTokenProvider 
{ 
    private readonly GenericXmlSecurityToken token; 

    public SamlSecurityTokenProvider(GenericXmlSecurityToken token) 
    { 
     this.token = token; 
    } 

    protected override SecurityToken GetTokenCore(TimeSpan timeout) 
    { 
     return token; 
    } 
} 
+0

Po dużo czasu spędzonego na poszukiwaniu rozwiązania wydaje się, że WS2007FederationHttpBinding z „Wiadomość” tryb zabezpieczeń nie jest przeznaczona do stosowania w w tym kontekście z powodu sprawdzania tożsamości serwera. Nadal możliwe jest używanie tego samego certyfikatu na odciążniku SSL i tożsamości usługi. – Bren

+0

Drugi tryb zabezpieczeń "TransportWithMessageCredential" jest przeznaczony do użycia z HTTPS, ale komunikat jest tylko zabezpieczony między klientem a odciorem SSL, również powiązanie musi zostać poprawione po stronie serwera, ponieważ serwer WWW nie obsługuje HTTPS zgodnie z : [link] (http://blog.hackedbrain.com/2006/09/26/how-to-ssl-passthrough-w-wcf-or-transportwithmessagecredential-over-plain-http/) [link] (https: //social.msdn.microsoft.com/Forums/vstudio/en-US/87a254c8-e9d1-4d4c-8f62-54eae497423f/how-to-ssl-passthrough- from-bigip?forum=wcf) – Bren

Odpowiedz

0

Jak skomentował pytanie: Po wielu czasie spędzonym na poszukiwaniu rozwiązania wydaje się, że WS2007FederationHttpBinding z „Wiadomość” tryb zabezpieczeń nie ma być używane w tym kontekście z powodu sprawdzania tożsamości serwera. Nadal możliwe jest używanie tego samego certyfikatu na odciążniku SSL i tożsamości usługi.

To rozwiązanie wybrałem zachować model bezpieczeństwa i rozwiązać mój problem