Domanda SOAP Client, Mutual Authentication, client certificate

  • mercoledì 13 giugno 2012 11:33
     
      Contiene codice

    Hi.

    I am developing a soap client for a web service of third part.

    The web service require a mutual authentication by client certificate.

    I have load the certificate in my client, but they doen't send the certificate to the server for authentication.

    This is my app.setting file:

    <configSections>
            <sectionGroup name="applicationSettings" type="System.Configuration.ApplicationSettingsGroup, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
                <section name="ConsolePCT.Properties.Settings" type="System.Configuration.ClientSettingsSection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false"/>
            </sectionGroup>
        </configSections>
        <applicationSettings>
            <ConsolePCT.Properties.Settings>
                <setting name="ConsolePCT_Test_WSServiziQueryBuilder" serializeAs="String">
                  <value>https://server.address.com</value>
                </setting>
            </ConsolePCT.Properties.Settings>
        </applicationSettings>

    this is my soap client code (generate by WSDL):

    public partial class WSServiziQueryBuilder : System.Web.Services.Protocols.SoapHttpClientProtocol {
            
            public WSServiziQueryBuilder() {
                this.Url = global::ConsolePCT.Properties.Settings.Default.ConsolePCT_Test_WSServiziQueryBuilder;
                if ((this.IsLocalFileSystemWebService(this.Url) == true)) {
                    this.UseDefaultCredentials = true;
                    this.useDefaultCredentialsSetExplicitly = false;
                }
                else {
                    this.useDefaultCredentialsSetExplicitly = true;
                }
            }
    
            protected override WebRequest GetWebRequest(Uri uri)
            {
                var request = (HttpWebRequest)base.GetWebRequest(uri);
                
                if (PreAuthenticate)
                {
                    NetworkCredential networkCredentials = Credentials.GetCredential(uri, "Basic");
                    if (networkCredentials != null)
                    {
                        byte[] credentialBuffer = new UTF8Encoding().GetBytes(networkCredentials.UserName + ":" + networkCredentials.Password);
                        request.Headers["Authorization"] = "Basic " + Convert.ToBase64String(credentialBuffer);
                    }
                    else
                    {
                        throw new ApplicationException("No network credentials");
                    }
                }
                request.Headers["X-WASP-User"] = XWASPUser.ToLower();
                request.KeepAlive = true;
                request.Method = "POST";
                request.Accept = "text/xml";
                request.AuthenticationLevel = AuthenticationLevel.MutualAuthRequired;
                return request;
            }
    
            public string XWASPUser { get; set; }
    
            public PCTExecuteHeader Header { get; set; }

    I have add the GetWebRequest method for insert some additional informations in soap header.

    this is my application code:

    static void Main(string[] args)
            {
                var certifcate = new X509Certificate2(@"C:\CertificatiPCT\Certificate.cer");
                var certifcate2 = new X509Certificate2(@"C:\CertificatiPCT\Certificate2.cer");
    
                var header = new PCTExecuteHeader
                    {
                        MustUnderstand = true,
                        Actor = "http://schemas.xmlsoap.org/soap/actor/next",
                        @group = "jpwusers",
                        name = "JPW",
                        role = "JPW"
                    };
    
                var client = new WSServiziQueryBuilder
                    {
                        UserAgent = "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.2; Trident/4.0; .NET CLR 1.1.4322; .NET CLR 1.0.3705; .NET CLR 2.0.50727; .NET CLR 3.0.04506.30; .NET CLR 3.0.04506.648; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729; .NET4.0C; .NET4.0E)",
                        SoapVersion = SoapProtocolVersion.Soap11
                    };
    
                client.ClientCertificates.Add(certifcate);
                client.ClientCertificates.Add(certifcate2);
                
                ServicePointManager.ServerCertificateValidationCallback += RemoteCertificateValidate;
    
                var netCredential = new NetworkCredential("jpw", "jpw");
                var uri = new Uri(client.Url);
                var credentials = netCredential.GetCredential(uri, "Basic");
                client.Credentials = credentials;
                client.Header = header;
                client.PreAuthenticate = true;
    
                var retval = client.getServiceNames();
                
            }
    
            private static bool RemoteCertificateValidate(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslpolicyerrors)
            {
                return true;
            }

    when i call getServiceNames method i get an http erro : HTTP 401: Authorization Required

    if i put a breakpoint in RemoteCertificateValidate method i see that the client certificate is not send to the server.

    Can someone help me?

    Thank's in advance. 

Tutte le risposte

  • mercoledì 13 giugno 2012 12:32
     
      Contiene codice

    ciao

    informativa di servizio: questo è un forum italiano, quindi cortesemente scrivici in italiano ke è meglio per tutti i lettori :)

    risposta:

    usa WCF (AddServiceReference) in VS al posto di AddWebReference

    quando poi userai WCF dovrai configurare il client

    questo è un esempio:

    <?xml version="1.0" encoding="utf-8" ?>
    <configuration>
      <system.serviceModel>
        <client>
          <endpoint name="autogenerato" behaviorConfiguration="clientCertificate"
                    address="autogenerato"
                    binding="basicHttpBinding" bindingConfiguration="bindingConfig"
                    contract="autogenerato"
                     />
        </client>
        <bindings>
          <basicHttpBinding>
            <binding name="bindingConfig">
              <security mode="Transport">
                <transport clientCredentialType="Certificate" />
              </security>
            </binding>
          </basicHttpBinding>
        </bindings>
        <behaviors>
          <endpointBehaviors>
            <behavior name="clientCertificate">
              <clientCredentials>
                <clientCertificate findValue="NOMEDELTUOCERTIFICATO"
                                   x509FindType="FindBySubjectName"
                                   storeLocation="LocalMachine"
                                   storeName="My"/>
              </clientCredentials>
            </behavior>
          </endpointBehaviors>
        </behaviors>
      </system.serviceModel>
    </configuration>

    facci sapere quando riesci a usare WCF così vediamo di aiutarti nella sua configurazione lato client

    a presto


    Antonio Esposito [MCT, MCPD, MCTS, MCP]
    dotnetlombardia.org | blog | web | @tonyexpo
    Italy


  • mercoledì 13 giugno 2012 14:13
     
      Contiene codice

    Scusa Antonio ma ero partito da un forum in inglese.. distrazione mia.

    Comunque, prima di usare AddWebReference avevo provato a usa AddServiceReference nel progetto di test, ma non funzionava.

    Le due utilità di VS non generano lo stesso codice pur partendo entrambe dallo stesso WSDL.

    In ogni caso ora sto seguendo le tue indicazioni, ho ricreato il client (ora con ServiceReference) e sto cercando di configurare la connessione come hai indicato tu, pero' ho una eccezione perchè non riesce a trovare il certificato.

    Il certificato mi sembra che sia presente (ho verificato che sia nei certificati personali usando certmgr.msc) ma non ha un nome.

    Ho provato a utilizzare il numero di serie, che ho individuato all'interno del certificato, ma mi dice "stringa esadecimale non valida".. sotto numero di serie, nelle proprietà del certificato trovo "‎0e 97 d7", percio' la mia configurazione è diventata:

    <clientCredentials>
                  <clientCertificate findValue="‎‎‎0e 97 d7" x509FindType="FindBySerialNumber" storeLocation="LocalMachine" storeName="My"/>
    </clientCredentials>

  • mercoledì 13 giugno 2012 14:26
     
     

    ciao

    per collegare correttamente il certificato 2 cose:

    in genere certmgr funziona su CurrentUser (da mettere al posto di LocalMachine)

    il thumbprint (l'esadecimale) va messo completo e senza gli spazi. attento se fai copia-incolla ke c'è 1 byte vuoto in più all'inizio

    ricorda che il certificato x essere valido deve avere la chiave privata altrimenti non riesci a fare la chiamata

    aggiornaci quanto prima

    a presto


    Antonio Esposito [MCT, MCPD, MCTS, MCP]
    dotnetlombardia.org | blog | web | @tonyexpo
    Italy
     

  • mercoledì 13 giugno 2012 14:46
     
      Contiene codice

    ok, perfetto, ora il certificato funziona.

    Ora pero' sto incontrando un problema che avevo già risolto in precedenza quando avevo utilizzato la WebReference. Il problema è che devo inserire un header nella chiamata al servizio. Avevo risolto in questo modo:

    Ho aggiunto una proprietà al client:

    public PCTHeader Header { get; set; }

    questa è classe PCTHeader:

    using System.Web.Services.Protocols;
        using System.Xml.Serialization;
    
        [XmlRoot(ElementName = "InvocationDomain", Namespace = "http://www.netserv.it/anag/security", IsNullable = false)]
        public class PCTHeader : SoapHeader
        {
            [XmlNamespaceDeclarations]
            public XmlSerializerNamespaces xmlsn
            {
                get
                {
                    var xsn = new XmlSerializerNamespaces();
                    xsn.Add("ns1", "http://www.netserv.it/anag/security");
                    return xsn;
                }
                set { }
            }
    
            [XmlAttribute]
            public string group { get; set; }
    
            [XmlAttribute]
            public string name { get; set; }
    
            [XmlAttribute]
            public string role { get; set; }
    
        }

    e poi nella cahiamata al metodo del client ho aggiunto un attributo:

    [SoapHeader("Header")]

    ho replicato questa cosa anche nel nuovo cliente WCF, ma l'header che viene generato (lo controllo tramite fiddler) non contiene le nuove informazioni..

  • mercoledì 13 giugno 2012 15:38
     
      Contiene codice
        [MessageContract(WrapperNamespace="http://ns1.test.com")]
        public class MyServiceRequest
        {
            [MessageHeader(Namespace="http://header.test.com")]
            public string HeaderProp { get; set; }
    
            [MessageBodyMember]
            public string BodyProp { get; set; }
        }
    

    ciao

    se vuoi gestire gli header, devi alterare il contratto di servizio mettendo come request un MessageContract

    poi nel message contract, vai a specificare cosa va in header e cosa in body


    Antonio Esposito [MCT, MCPD, MCTS, MCP]
    dotnetlombardia.org | blog | web | @tonyexpo
    Italy
     

  • giovedì 14 giugno 2012 08:23
     
      Contiene codice

    Ciao, ho sistemato l'invio degli header.

    Il messaggio che dovrei ottenere è questo:

    <?xml version="1.0" encoding="utf-8"?>
    <soap:Envelope 
    	xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" 
    	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    	xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <soap:Header>
    	<ns1:InvocationDomain 
    		xmlns:ns1="http://www.netserv.it/anag/security" 
    		soap:mustUnderstand="1" 
    		soap:actor="http://schemas.xmlsoap.org/soap/actor/next" 
    		group="jpwusers" 
    		name="JPW" 
    		role="JPW"/> 
    </soap:Header> 
    <soap:Body> 
    	<getServiceNames xmlns="urn:CONS-SICC-BE" /> 
    </soap:Body> 
    </soap:Envelope>

    Il messaggio che ottengo invece è questo:

    <s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
    <s:Header>
    <h:Header s:actor="http://schemas.xmlsoap.org/soap/actor/next"
    s:mustUnderstand="1"
    group="jpwusers" 
    name="JPW" 
    role="JPW" 
    xmlns:h="http://www.netserv.it/anag/security" 
    xmlns="http://www.netserv.it/anag/security"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"x
    mlns:xsd="http://www.w3.org/2001/XMLSchema"/>
    </s:Header>
    <s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <getServiceNames xmlns="urn:CONS-SICC-BE"/>
    </s:Body>
    </s:Envelope>

    che è identico a parte gli alias dei namespace e il loro posizionamento nel messaggio, ma questo non dovrebbe essere un problema.

    Ora mi manca da aggiustare un'altra parte che avevo già sistemato nella versione precedente in questo modo e che riguarda l'invio di informazioni non nell'header del messaggio, ma della chiamata al servizio. Il risultato dovrebbe essere questo:

    Accept-Encoding: gzip,deflate
    Content-Type: text/xml
    Authorization: Basic anB3Ompwdw==
    X-WASP-User: kkkzzzzyyyffff
    Content-Length: 984
    Host: 89.119.251.100:8081
    Connection: Keep-Alive
    User-Agent: Apache-HttpClient/4.1.1 (java 1.5)

    in particolare devo inserire il campo Authorization e X-WASP-User. Avevo risolto modificando il client con questo codice:

    protected override WebRequest GetWebRequest(Uri uri)
            {
                var request = (HttpWebRequest)base.GetWebRequest(uri);
                
                if (PreAuthenticate)
                {
                    NetworkCredential networkCredentials = Credentials.GetCredential(uri, "Basic");
                    if (networkCredentials != null)
                    {
                        byte[] credentialBuffer = new UTF8Encoding().GetBytes(networkCredentials.UserName + ":" + networkCredentials.Password);
                        request.Headers["Authorization"] = "Basic " + Convert.ToBase64String(credentialBuffer);
                    }
                    else
                    {
                        throw new ApplicationException("No network credentials");
                    }
                }
                request.Headers["X-WASP-User"] = XWASPUser.ToLower();
                return request;
            }

    Qual'è l'equivalente in WCF?

    Grazie in anticipo per l'aiuto..

  • giovedì 14 giugno 2012 09:35
     
      Contiene codice

    Mi rispondo da solo, per informazione di tutti.

    Per inserire header direttamente nella chiamata al servizio, anzichè nel messaggio soap sono sufficienti queste poche righe di codice:

    var client = new PCTClient.ServiziQueryBuilderClient();
                var prop = new HttpRequestMessageProperty();
                byte[] credentialBuffer = new UTF8Encoding().GetBytes("aaa" + ":" + "bbb");
                prop.Headers["Authorization"] = "Basic " + Convert.ToBase64String(credentialBuffer);
    
                 using (new OperationContextScope(client.InnerChannel))
                 {
                     OperationContext.Current.OutgoingMessageProperties[HttpRequestMessageProperty.Name] = prop;
                     var serviceNames = client.getServiceNames();
                 }

    Questo inserisce l'headers Authorization prima del messaggio soap valorizzato a "Basic YWFhOmJiYg=="..

    Ora sono al punto di partenza. Ottengo un errore HTTP 401 dal server e non capisco se il client invia o meno il certificato per la mutua autenticazione..

  • giovedì 14 giugno 2012 09:42
     
      Contiene codice

    ciao

    è ovvio ke nn funziona

    o autentichi con X509 o autentichi con basic

    io pensavo che volessi aggiungere degli header veri (custom)

    non autenticarti manualmente con l'header della basic authentication che WCF supporta automaticamente e non ci sarebbe stato bisogno di scrivere quel codice, ma semplicemente cambiare il config

    probabilmente tu non usi davvero la mutua autenticazione x509, ma la mutua autenticazione nel senso che fai login con basic e validi il certificato server a ritroso

    ma questo è tutt'altro scenario

    questo un config di esempio:

    <?xml version="1.0" encoding="utf-8" ?>
    <configuration>
      <system.serviceModel>
        <client>
          <endpoint name="autogenerato" behaviorConfiguration="clientCertificate"
                    address="autogenerato"
                    binding="basicHttpBinding" bindingConfiguration="bindingConfig"
                    contract="autogenerato"
                     />
        </client>
        <bindings>
          <basicHttpBinding>
            <binding name="bindingConfig">
              <security mode="Transport">
                <transport clientCredentialType="Basic" />
              </security>
            </binding>
          </basicHttpBinding>
        </bindings>
        <behaviors>
          <endpointBehaviors>
            <behavior name="clientCertificate">
              <clientCredentials>
                <serviceCertificate>
                  <authentication certificateValidationMode="PeerOrChainTrust"
                                  revocationMode="NoCheck"
                                  trustedStoreLocation="CurrentUser"/>
                  <!-- validazione automatica in peer o chain trust
                                  devi aggiungere il cert server in trusted peoples-->
                  <defaultCertificate findValue="123131231231"
                                      x509FindType="FindByThumbprint"
                                      storeLocation="CurrentUser"
                                      storeName=""/>
                  <!-- autenticazione manuale del cert server, devi avere il cert da qualche
                                      parte esplicita e dirgli qual'è -->
                </serviceCertificate>
              </clientCredentials>
            </behavior>
          </endpointBehaviors>
          <serviceBehaviors>
            <behavior name="">
              <serviceMetadata httpGetEnabled="true" />
              <serviceDebug includeExceptionDetailInFaults="false" />
            </behavior>
          </serviceBehaviors>
        </behaviors>
      </system.serviceModel>
    </configuration>

    poi per autenticarti lato client:

                var client = new ServiceReference1.MyServiceClient();
                client.ClientCredentials.UserName.UserName="username";
                client.ClientCredentials.UserName.Password = "pwd";
    

    considera che il binding basic così impostato usa SSL quindi devi andare in HTTPS

    aggiornaci quando puoi

    a presto


    Antonio Esposito [MCT, MCPD, MCTS, MCP]
    dotnetlombardia.org | blog | web | @tonyexpo
    Italy
     

  • giovedì 14 giugno 2012 13:22
     
      Contiene codice

    Ciao, a scanso di equivoci ho chiesto chiarimenti via mail al gestore del servizio (Ministero della giustizia....) riguardo le procedure di autenticazione.

    Ti riepilogo quello che ho in mano io e che il ministero mi ha fornito:

    - Un progetto di esempio che gira su SOAP UI e che utilizza un canale non protetto (http) per interrogare un webservice di test e che utilizza l'autenticazione Basic con nome utente e password per l'autenticazione (se rimuovo nome utente e password il web service non mi autentica: "L'utente NOBODY non può eseguire l'autenticazione")

    - Il web service vero e proprio gira su un canale protetto (https) e non esiste un progetto di esempio per tale tipo di canale.......

    - So che ogni utente che che si registra al servizio viene munito di certificato da utilizzare per la "mutua autenticazione" (almeno così dice la documentazione che il ministero mi ha fornito), in abbinamento al codice fiscale del soggetto da inserire come header del messaggio con un parametro custom che si chiama X-WASP-User. Io sono in possesso sia di un certificato valido che del corrispondente codice fiscale.

    E' presumibile che il certificato sostituisca le credenziali username e password, ma non ho trovato nessuna conferma su questo punto nella documentazione.

    Ho mandato una richiesta di delucidazioni al supporto tecnico del Ministero. ora sono in attesa..

    Nel frattempo ho fatto alcune prove. Se non inserisco il codice che ho postato sopra, ma utilizzo semplicemente la configurazione con autenticazione basic e imposto le ClientCredentials, ho notato che l'informazione sull'autenticazione nel messaggio inviato al server non è presente. Manca proprio l'header Authorization.. con il codice che ho postato invece viene inserito.

    Poi ho provato a usare il certificato di cui sono in possesso con quest configurazione:

    <configuration>
        <system.serviceModel>
            <bindings>
                <basicHttpBinding>
                    <binding name="ServiziQueryBuilderSOAPBinding" closeTimeout="00:01:00"
                        openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00"
                        allowCookies="false" bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard"
                        maxBufferSize="65536" maxBufferPoolSize="524288" maxReceivedMessageSize="65536"
                        messageEncoding="Text" textEncoding="utf-8" transferMode="Buffered"
                        useDefaultWebProxy="true">
                        <readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"
                            maxBytesPerRead="4096" maxNameTableCharCount="16384" />
                        <security mode="Transport">
                            <transport clientCredentialType="Certificate" />
                            <message clientCredentialType="UserName" algorithmSuite="Default" />
                        </security>
                    </binding>
                </basicHttpBinding>
            </bindings>
          <behaviors>
            <endpointBehaviors>
              <behavior name="clientCertificate" >
                <clientCredentials>
                  <clientCertificate findValue="0e97d7" x509FindType="FindBySerialNumber" storeLocation="CurrentUser" storeName="My"/>
                </clientCredentials>
              </behavior>
            </endpointBehaviors> 
          </behaviors>
            <client>
                <endpoint address="https://ext.processotelematico.giustizia.it/pda/pycons/GLMI/JPW_SICID" binding="basicHttpBinding"
                    bindingConfiguration="ServiziQueryBuilderSOAPBinding" contract="PCTClient.ServiziQueryBuilder" behaviorConfiguration="clientCertificate"
                    name="ServiziQueryBuilderSOAPPort" />
            </client>
        </system.serviceModel>
    </configuration>

    Parte della configurazione è stata generata durante la creazione del client partendo dal WSDL, parte è stata modificata secondo le tue indicazioni precedenti

    In questo caso la risposta del server è questa:"La richiesta HTTP non è autorizzata con lo schema di autenticazione client 'Anonymous'. Intestazione di autenticazione ricevuta dal server: ''

    Ho l'impressione che il server non riceva il certificato dal client..

  • giovedì 14 giugno 2012 15:51
     
     

    da quello che mi dici, confido nel fatto che tu voglia usare la Basic authentication, più l'autenticazione del certificato server per la mutua autenticazione

    la configurazione corretta dovrebbe essere da config con la Transport in Basic, che va da sola in https e mette nell'header HTTP_AUTHORIZATION

    il certificato è per autenticare il server non il client

    dovresti avere tutto il necessario nel mio precedente post

    impostare le client credentials senza la giusta configurazione nel .config non serve perchè non vengono serializzate le informazioni di sicurezza

    facci sapere

    a presto


    Antonio Esposito [MCT, MCPD, MCTS, MCP]
    dotnetlombardia.org | blog | web | @tonyexpo
    Italy
     

  • giovedì 14 giugno 2012 15:59
     
     

    Ciao Antonio,

    You wrote on 14/06/2012 :

    il certificato è per autenticare il server non il client

    se è un client certificate serve proprio per autenticare il client.

    .m



    blog @ //milestone.topics.it
  • venerdì 15 giugno 2012 10:07
     
      Contiene codice

    Ciao Antonio,

    ti riporto quello che la documentazione che mi è stata fornita dal ministero dice in merito all'autenticazione:

    "Il protocollo https è inteso in mutua autenticazione e quindi il chiamante deve presentare il certificato di un utente censito sul ReGIndE. Il certificato deve essere rilasciato da una CA accreditata da DigitPA"

    Quello che mi viene da pensare è che la Basic Authentication sia stata usata solo per l'ambiente di prova, mentre per l'ambiente reale venga sostituita dal certificato che l'utente possiede..

    Io il certificato valido ce l'ho, ma se provo a usare l'utenticazione che ti ho postato sopra e ce ti riporto qui per semplicità:

    <security mode="Transport">
                            <transport clientCredentialType="Certificate" />
                            <message clientCredentialType="UserName" algorithmSuite="Default" />
                        </security>

    Ottengo in risposta dal server "La richiesta HTTP non è autorizzata con lo schema di autenticazione client "Anonymous" ecc. ecc. che ti ho postato sopra.

    Sicuramente mi sbaglierò, ma leggendo la risposta mi sembra che il server non riceva il certificato e quindi non sia in grado di capire chi sta facendo la richiesta.

    C'è un modo per vedere se il client invia o meno il certificato al server?

    PS. Resto sempre in attesa di una risposta di conferma alla mia ipotesi dal ministero.. spero rispondano al più presto.

  • venerdì 15 giugno 2012 10:21
     
     

    ciao

    ricapitoliamo: quindi la Basic non esiste!

    usi il certificato per l'autenticazione client (quindi di mutuo non c'è niente a meno che tu non stia rivalidando il certificato del server)

    l'anonymous avviene quando non vai direttamente in modalità autenticata, ma inizi la comunicazione appunto anonimamente

    se hai configurato correttamente il tutto, non dovesti avere questo problema

    puoi postare tutto il .config del client??

    grazie


    Antonio Esposito [MCT, MCPD, MCTS, MCP]
    dotnetlombardia.org | blog | web | @tonyexpo
    Italy
     

  • venerdì 15 giugno 2012 10:26
     
      Contiene codice

    Ciao,

    si, la basic non esiste, da quello che ho capito (aspetto conferma formale via mail)

    Questo è il config lato client:

    <configuration>
        <system.serviceModel>
            <bindings>
                <basicHttpBinding>
                    <binding name="ServiziQueryBuilderSOAPBinding" closeTimeout="00:01:00"
                        openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00"
                        allowCookies="false" bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard"
                        maxBufferSize="65536" maxBufferPoolSize="524288" maxReceivedMessageSize="65536"
                        messageEncoding="Text" textEncoding="utf-8" transferMode="Buffered"
                        useDefaultWebProxy="true">
                        <readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"
                            maxBytesPerRead="4096" maxNameTableCharCount="16384" />
                        <security mode="Transport">
                            <transport clientCredentialType="Certificate" proxyCredentialType="None" realm="" />
                        </security>
                    </binding>
                </basicHttpBinding>
            </bindings>
          <behaviors>
            <endpointBehaviors>
              <behavior name="clientCertificate" >
                <clientCredentials >
                  <clientCertificate findValue="0e97d7" x509FindType="FindBySerialNumber" storeLocation="CurrentUser" storeName="My" />
                </clientCredentials>
              </behavior>
            </endpointBehaviors> 
          </behaviors>
            <client>
                <endpoint address="https://ext.processotelematico.giustizia.it/pda/pycons/GLMI/JPW_SICID"
                    behaviorConfiguration="clientCertificate" binding="basicHttpBinding"
                    bindingConfiguration="ServiziQueryBuilderSOAPBinding" contract="PCTClient.ServiziQueryBuilder"
                    name="ServiziQueryBuilderSOAPPort" />
            </client>
        </system.serviceModel>
    </configuration>

    Grazie per l'aiuto e la pazienza..

  • venerdì 15 giugno 2012 10:32
     
     

    prova ad usare il wsHttpBinding o il ws2007HttpBinding che il problema è nell'implementazione della chiamata

    a credere ad apache il basic inizia la comunicazione in anonymous.....

    se non riesci così, dovrai configurare un custom-binding

    a presto


    Antonio Esposito [MCT, MCPD, MCTS, MCP]
    dotnetlombardia.org | blog | web | @tonyexpo
    Italy
     

  • venerdì 15 giugno 2012 13:10
     
      Contiene codice

    Ciao,

    ho provato a configurare un custom-binding minimale in questo modo:

    <customBinding>
                <binding name="ServiziQueryBuilderSOAPBinding" closeTimeout="00:01:00"
                    openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00">
                  <transactionFlow />
                  <security authenticationMode="CertificateOverTransport"/>
                  <textMessageEncoding messageVersion="Soap11" />
                  <httpsTransport requireClientCertificate="True" />
                </binding>
              </customBinding>

    ma ottengo questa eccezione appena tento di chiamare il metodo sul servizio: "Chiave privata non presente nel certificato X.509."

    e in effetti la chiave privata non è presente nel certificato.

    E' indispensabile che la chiave privata sia presente nel certificato?

    Perchè prima di usare un custom-binding questo problema non si è presentato?

    Grazie...

  • mercoledì 27 giugno 2012 16:12
     
     

    Salve, Michele

    sto affrontando un problema del tutto simile. Volevo chiederti se nel frattempo hai risolto e in che modo.

    Grazie :)

  • venerdì 29 giugno 2012 13:56
     
     

    Ciao,

    al momento non ho ancora risolto del tutto..

    o meglio, ho risolto il problema del certificato.. funziona solo se è presente la smartcard/chiavetta usb che contiene i certificati.

    Cmq ho dovuto abbandonare WCF e sono passato a un proxy che estende la classe SoapHttpClientProtocol.

    Ora l'autenticazione funziona, pero' ho un errore strano HTTP 503: Proxy error, bad gateway che non risesco a risolvere.

    La cosa strana è che ho inviato il messaggio soap al supporto tecnico del gestore del servizio e mi ha detto che loro l'hanno provata e funziona.

    A questo punto credo che il problema dipenda dagli header che il client invia prima di spedire il messaggio vero e proprio, solo che fino ad oggi non ho trovato un modo per manipolarli come vorrei..


  • sabato 28 luglio 2012 13:43
     
     

    Ciao,

    La "Mutual SSL autentication" richiede che il client esponga un certificato (x509) con chiave privata: http://www.codeproject.com/Articles/326574/An-Introduction-to-Mutual-SSL-Authentication

    Il Ministero della Giustizia ha adottato questo tipo di autenticazione per l'accesso al Processo Telmatico: http://www.processotelematico.giustizia.it/pdapublic/

    Io sto progettando un software per l'accesso a tale "web service" ma la maggior parte dei miei utenti (Avvocati) possiede una smart card che (per motivi di sicurezza) NON CONSENTE l'esportazione della chave privata. Per tale motivo non posso esportare il certificato in formato PKCS #12 (.pfx).

    Ho provato ad autenticarmi utilizzando un certificato in formato .cer ed in formato PKCS #7 (vedi codice c#), ma il server mi ha restituito il seguente messaggio di errore: "502 Proxy Error The proxy server received an invalid response from an upstream server The proxy server could not handle the request Error reading from remote server Apache/2.2.3 (Red Hat) Server at Port 443".

    Qualcuno potrebbe, gentilmente, dirmi:

    1. Se esiste un modo per effettuare la "Mutual authentication" lato client senza esporre la chiave privata.

    2. Se esiste un modo per recuperare (dalla Smart Card) la chiave privata NON ESPORTABILE e con essa creare un clone del certificato in formato .pfx

    3. Se è possibile effettuare la "Mutual authentication" lato client in qualche altro modo?

    Sono graditi frammenti di codice in C#

    Grazie :-)

    Lello Passannanti

    **********************************************

    /// <summary>
    ///
    /// </summary>
    /// <param name="url"></param>
    /// <returns></returns>
    public static HttpWebRequest CreateWebRequest(string url)
    {
        Uri uri = new Uri(url);

        HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(uri);
        webRequest.Headers.Add("SOAP:Action");
        webRequest.Headers.Add("X-WASP-User", "psssrl52s19h703u");
        webRequest.KeepAlive = true;
        webRequest.ContentType = "text/xml;charset=\"utf-8\"";
        webRequest.Accept = "text/xml";
        webRequest.Method = "POST";
        webRequest.AuthenticationLevel = AuthenticationLevel.MutualAuthRequired;
        webRequest.ClientCertificates.Add(certificate);
       
        return webRequest;

    }


    • Modificato Juris Quick sabato 28 luglio 2012 13:47 x
    • Modificato Juris Quick sabato 28 luglio 2012 13:51 ortografia
    • Modificato Juris Quick sabato 28 luglio 2012 13:52 ortografia
    • Modificato Juris Quick sabato 28 luglio 2012 13:53 ortografia
    • Modificato Juris Quick sabato 28 luglio 2012 13:54 ortografia
    • Modificato Juris Quick sabato 28 luglio 2012 13:55 ortografia
    • Modificato Juris Quick sabato 28 luglio 2012 13:58 ortografia
    • Modificato Juris Quick sabato 28 luglio 2012 14:16 ortografia
    • Modificato Juris Quick sabato 28 luglio 2012 14:17 ortografia
    • Modificato Juris Quick sabato 28 luglio 2012 14:24 ortografia
    • Proposto come risposta Juris Quick sabato 28 luglio 2012 16:54
    • Proposta come risposta annullata Juris Quick sabato 28 luglio 2012 16:54
    • Modificato Juris Quick sabato 28 luglio 2012 16:56 ortografia
    • Modificato Juris Quick sabato 28 luglio 2012 17:06
    • Modificato Juris Quick sabato 28 luglio 2012 18:11
    • Modificato Juris Quick sabato 28 luglio 2012 18:26
    • Modificato Juris Quick domenica 29 luglio 2012 22:31
    • Modificato Juris Quick domenica 29 luglio 2012 22:34
    • Modificato Juris Quick domenica 29 luglio 2012 22:36
    • Modificato Juris Quick domenica 29 luglio 2012 22:38
    • Modificato Juris Quick domenica 29 luglio 2012 22:38
    • Modificato Juris Quick domenica 29 luglio 2012 22:40
    • Modificato Juris Quick domenica 29 luglio 2012 22:45
    • Modificato Juris Quick domenica 29 luglio 2012 22:46
    • Modificato Juris Quick lunedì 30 luglio 2012 05:32
    • Modificato Juris Quick lunedì 30 luglio 2012 05:33
    • Modificato Juris Quick lunedì 30 luglio 2012 05:34
    • Modificato Juris Quick martedì 31 luglio 2012 05:27
    •  
  • martedì 14 agosto 2012 09:25
     
     

    PROBLEMA RISOLTO:

    L'errore: 502 (bad gateway) non dipendeva dai certificati ma dal fatto che, per la trasmissione dei dati, il proxy del Ministero della Giustiza utilizza il protocollo HTTP 1.0 mentre il mio applicativo utilizzava il protocollo HTTP 1.1.

    Per correggere l'errore 502 (bad gateway) è bastato aggiungere, nella chiamata al servizio, la seguente istruzione (vedi codice). Ora riesco a connettermi correttamente. Spero che questo "post" possa essere utile ad altri.

    Cordiali saluti

    Lello Passannanti

    =====================================================
    public static HttpWebRequest CreateWebRequest(string url)
    {
         Uri uri = new Uri(url);
         HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(uri);

         //Questa istruzione corregge l'errore 502 (Bad gateway)
         webRequest.ProtocolVersion = HttpVersion.Version10;
     
         webRequest.Proxy = null;
         webRequest.Headers.Add("SOAP:Action");
         webRequest.KeepAlive = true;
         webRequest.ContentType = "text/xml;charset=\"utf-8\"";
         webRequest.Accept = "text/xml";
         webRequest.Method = "POST";
         webRequest.AuthenticationLevel = AuthenticationLevel.MutualAuthRequired;
         if (certificate != null)
         {
            webRequest.ClientCertificates.Add(certificate);
         }

         return webRequest;

    }


    • Modificato Juris Quick martedì 14 agosto 2012 09:28
    •  
  • giovedì 27 dicembre 2012 21:28
     
     

    Ciao,

    sto implementando per alcuni clienti il collegamento PCT, volevo chiederti se hai poi risolto i tuoi problemi e se eventualmente hai a disposizione una libreria o del codice (anche a pagamento) per il collegamento.

    Se ti interessa puoi contattarmi a chiccof@libero.it

    Grazie