2014-11-11 7 views
0

Моя конкретная проблема что-то вроде этого:Вызов службы WCF с сертификатом от клиентского приложения, не имея интерфейс контракта

  • Я могу ссылаться на WCF службы динамически, но я должен предоставить сертификат.
  • Мы не хотим использовать app.config.
  • Основная проблема заключается в том, что служба WCF является сторонним URL-адресом.
  • На самом деле, я получаю исключение, пока вызываю экземпляр, что сертификат не предоставляется.
  • Мой код-то вроде этого:

    try 
        { 
         // Define the metadata address, contract name, operation name, 
         // and parameters. 
         // You can choose between MEX endpoint and HTTP GET by 
         // changing the address and enum value. 
         Uri mexAddress = new Uri("http://Some3rdPartyURL.svc?wsdl");//Some 3rd party url 
         // For MEX endpoints use a MEX address and a 
         // mexMode of .MetadataExchange 
    
    
         MetadataExchangeClientMode mexMode = MetadataExchangeClientMode.HttpGet; 
    
         string contractName = "IService";//"";//3rd party service name 
         string operationName = "SendMethod";//3rd party method name 
         object[] args = new object[] { "", "", "0" };//3rd party required parameters 
         //object[] operationParameters = new object[] { /*1, 2*/args }; 
    
         // Get the metadata file from the service. 
         MetadataExchangeClient mexClient = 
         new MetadataExchangeClient(mexAddress, mexMode); 
         mexClient.ResolveMetadataReferences = true; 
         MetadataSet metaSet = mexClient.GetMetadata(); 
    
         // Import all contracts and endpoints 
         WsdlImporter importer = new WsdlImporter(metaSet); 
    
         Collection<ContractDescription> contracts = 
           importer.ImportAllContracts(); 
         ServiceEndpointCollection allEndpoints = importer.ImportAllEndpoints(); 
    
         // Generate type information for each contract 
         ServiceContractGenerator generator = new ServiceContractGenerator(); 
    
         var endpointsForContracts = new Dictionary<string, IEnumerable<ServiceEndpoint>>(); 
    
         foreach (ContractDescription contract in contracts) 
         { 
          generator.GenerateServiceContractType(contract); 
          // Keep a list of each contract's endpoints 
          endpointsForContracts[contract.Name] = allEndpoints.Where(
           se => se.Contract.Name == contract.Name).ToList(); 
         } 
    
         if (generator.Errors.Count != 0) 
          throw new Exception("There were errors during code compilation."); 
    
         // Generate a code file for the contracts 
         CodeGeneratorOptions options = new CodeGeneratorOptions(); 
         options.BracingStyle = "C"; 
         CodeDomProvider codeDomProvider = CodeDomProvider.CreateProvider("C#"); 
    
         // Compile the code file to an in-memory assembly 
         // Don't forget to add all WCF-related assemblies as references 
         CompilerParameters compilerParameters = new CompilerParameters(
          new string[] { 
           "System.dll", "System.ServiceModel.dll", 
           "System.Runtime.Serialization.dll"}); 
         compilerParameters.GenerateInMemory = true; 
    
         CompilerResults results = codeDomProvider.CompileAssemblyFromDom(
          compilerParameters, generator.TargetCompileUnit); 
    
         if (results.Errors.Count > 0) 
         { 
          throw new Exception("There were errors during generated code compilation"); 
         } 
         else 
         { 
          // Find the proxy type that was generated for the specified contract 
          // (identified by a class that implements 
          // the contract and ICommunicationbject) 
          Type clientProxyType = results.CompiledAssembly.GetTypes().First(
           t => t.IsClass && 
            t.GetInterface(contractName) != null && 
            t.GetInterface(typeof(ICommunicationObject).Name) != null); 
    
    
          // Get the first service endpoint for the contract 
          ServiceEndpoint se = endpointsForContracts[contractName].First(); 
          //se = endpointsForContracts[contractName].First(); 
    
          WSHttpBinding wsBinding = this.fillWsHttpBinding();     
          string encodeValue = "MIIFazCCBFO****"; // here we should use the encoded certificate value generated by svcutil.exe. 
          X509Certificate2Collection supportingCertificates = new X509Certificate2Collection(); 
          supportingCertificates.Import(Convert.FromBase64String(encodeValue)); 
          X509Certificate2 primaryCertificate = supportingCertificates[0]; 
          supportingCertificates.RemoveAt(0); 
          EndpointIdentity.CreateX509CertificateIdentity(primaryCertificate, supportingCertificates); 
          EndpointIdentity identity = EndpointIdentity.CreateX509CertificateIdentity(primaryCertificate); 
          var endpoint = new EndpointAddress(mexAddress, identity); 
    
          se.Binding = wsBinding; 
          se.Address = endpoint; 
    
          // Create an instance of the proxy 
          // Pass the endpoint's binding and address as parameters 
          // to the ctor     
          object instance = results.CompiledAssembly.CreateInstance(
           clientProxyType.Name, 
           false, 
           System.Reflection.BindingFlags.CreateInstance | BindingFlags.Public | BindingFlags.Instance, 
            null, 
           new object[] { se.Binding, se.Address }, CultureInfo.CurrentCulture, null); 
    
          var methodInfo = instance.GetType().GetMethod(operationName); 
          var methodParams = methodInfo.GetParameters(); 
          int count = args.Count(); 
          object[] args2 = new object[count]; 
          int i = 0; 
          foreach (var service1 in methodParams) 
          { 
           args2[i] = Convert.ChangeType(args[i], Type.GetType("System." + service1.ParameterType.Name)); 
           i += 1; 
          } 
          Object retVal = instance.GetType().GetMethod(operationName).Invoke(instance, args2);/*Getting Error that certificate not provided???*/ 
         } 
        } 
        catch (Exception ex) 
        { 
         string error = ex.ToString(); 
         MessageBox.Show("Error Invoking Method: " + ex.Message); 
        } 
    

    частный WSHttpBinding fillWsHttpBinding() {

    WSHttpBinding wsBinding = new WSHttpBinding(); 
        wsBinding.CloseTimeout = new TimeSpan(0, 1, 0); 
        wsBinding.OpenTimeout = new TimeSpan(0, 10, 0); 
        wsBinding.ReceiveTimeout = new TimeSpan(0, 10, 0); 
        wsBinding.SendTimeout = new TimeSpan(0, 5, 30); 
        wsBinding.BypassProxyOnLocal = false; 
        wsBinding.TransactionFlow = false; 
        wsBinding.HostNameComparisonMode = HostNameComparisonMode.StrongWildcard; 
        wsBinding.MaxBufferPoolSize = 524288L; 
        wsBinding.MaxReceivedMessageSize = 10485760L; 
        wsBinding.MessageEncoding = WSMessageEncoding.Text; 
        wsBinding.TextEncoding = Encoding.UTF8; 
        wsBinding.UseDefaultWebProxy = true; 
        wsBinding.AllowCookies = false; 
    
        wsBinding.ReaderQuotas.MaxDepth = 32; 
        wsBinding.ReaderQuotas.MaxStringContentLength = 8192; 
        wsBinding.ReaderQuotas.MaxArrayLength = 10485760; 
        wsBinding.ReaderQuotas.MaxNameTableCharCount = 16384; 
    
        wsBinding.ReliableSession.Ordered = true; 
        wsBinding.ReliableSession.InactivityTimeout = TimeSpan.FromMinutes(10); 
        wsBinding.ReliableSession.Enabled = false; 
    
        wsBinding.Security.Mode = SecurityMode.Message; 
        wsBinding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Windows; 
        wsBinding.Security.Transport.ProxyCredentialType = HttpProxyCredentialType.None; 
        wsBinding.Security.Transport.Realm = ""; 
    
        wsBinding.Security.Message.ClientCredentialType = MessageCredentialType.Certificate; 
        wsBinding.Security.Message.NegotiateServiceCredential = true; 
        wsBinding.Security.Message.AlgorithmSuite = System.ServiceModel.Security.SecurityAlgorithmSuite.Basic256; 
    
        return wsBinding; 
    } 
    
+0

Опубликовать информацию об исключениях ... Как другие люди должны знать, какую ошибку вы получаете, если не включаете ее в свой вопрос? – user469104

+0

Прошу прощения. На самом деле, я получаю исключение при вызове экземпляра: Объект retVal = instance.GetType(). GetMethod (operationName) .Invoke (instance, args2); См. Исключение: System.Reflection.TargetInvocationException: Исключение было выбрано целью вызова. ---> System.InvalidOperationException: сертификат клиента не предоставляется. Укажите клиентский сертификат в ClientCredentials. –

ответ

0

Где вы устанавливаете сертификат на EndpointIdentity заставляет его использовать для подтвердите идентификатор , номер. Вы не установили учетные данные клиента, используя instance.ClientCredentials.ClientCertificate.SetCertificate(...). Вам нужно будет получить ClientCredentials из ClientBase <> с помощью отражения. См. http://msdn.microsoft.com/en-us/library/ms732391%28v=vs.110%29.aspx.

var credentialProperty = instance.GetType().GetProperty("ClientCredentials"); 
var credentials = (ClientCredentials)credentialProperty.GetValue(instance, null); 
credentials.ClientCertificate.SetCertficate(...); 

Вы также получили два вызова EndpointIdentity.CreateX509CertificateIdentity, не обращая внимания на выход одного из них.

+0

Спасибо, Но проблема в том, что я не получаю возможность устанавливать сертификат в объекте, названном экземпляром в приведенном выше коде? –

+0

Вам нужно будет использовать отражение, чтобы получить свойство ClientCredentials из «экземпляра». В fileWsHttpBinding() вам не нужно устанавливать Security.Transport.ClientCredentialType. –

+0

Да, я согласен с тобой. Я уже пробовал размышлять, чтобы получить свойство ClientCredentials из «экземпляра», но не смог установить значение свойства. Я получаю ниже исключения: System.ArgumentException: метод набора свойств не найден. at System.Reflection.RuntimePropertyInfo.SetValue (Object obj, Object value, BindingFlags invokeAttr, Binder binder, Object [] index, CultureInfo culture) at System.Reflection.RuntimePropertyInfo.SetValue (Object obj, Object value, Object [] index) –