CMDBuild Forum

Webservices e .NET

Salve,
stiamo provando ad accedere tramite webservices al cmdb, l'ambiente utilizzato è il seguente:
VS 2008, .NET Framework 3.5
CMDBuild v. 1.1.1

Abbiamo realizzato un'applicazione Web che richiede accesso al CMDB per prelevare delle informazioni, lo stralcio di codice
che abbiamo utilizzato per l'accesso al CMDB è il seguente:

Dim myWS As Webservices = New Webservices()
myWS.Credentials = New System.Net.NetworkCredential("user", "password")
Try
    myWS.getActivityMenuSchema() 
Catch ex As Exception
    Console.Write(ex.Message)
End Try

dove user e password sono definiti nel cmdb, il metodo (myWS.getActivityMenuSchema) utilizzato è puramente esemplificativo.

Il file policy.xml sito nella directory tomcat/webapps/cmdbuild/WEB-INF/conf è identico a quello da voi suggerito:

<?xml version="1.0" encoding="UTF-8"?>

<wspolicy wsu:Id="UTOverTransport"
            xmlns:wsu="
http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"
            xmlns:wsp="
http://schemas.xmlsoap.org/ws/2004/09/policy">
    <wsp:ExactlyOne>
        <sp:SignedSupportingTokens xmlns:sp="
http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702">     
                <wspolicy>
                    <sp:UsernameToken sp:IncludeToken="
http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702/IncludeToken/AlwaysToRecipient">
                             <wspolicy>
                                <sp:HashPassword/>
                             </wspolicy>
                    </sp:UsernameToken>
               </wspolicy>
        </sp:SignedSupportingTokens>
            <ramp:RampartConfig xmlns:ramp="
http://ws.apache.org/rampart/policy">
            </ramp:RampartConfig>
    </wsp:ExactlyOne>
</wspolicy>

Al tentativo di accesso ottengo i seguenti messaggio di errore presenti nel cmdbuild.log

ERROR 2009-12-15 18:03:01 [org.apache.axis2.engine.AxisEngine] WSDoAllReceiver: Incoming message does not contain required Security header
org.apache.axis2.AxisFault: WSDoAllReceiver: Incoming message does not contain required Security header
        at org.apache.rampart.handler.WSDoAllReceiver.processBasic(WSDoAllReceiver.java:221)
        at org.apache.rampart.handler.WSDoAllReceiver.processMessage(WSDoAllReceiver.java:86)
        at org.apache.rampart.handler.WSDoAllHandler.invoke(WSDoAllHandler.java:72)
        at org.apache.axis2.engine.Phase.invoke(Phase.java:317)
        at org.apache.axis2.engine.AxisEngine.invoke(AxisEngine.java:264)
        at org.apache.axis2.engine.AxisEngine.receive(AxisEngine.java:163)
        at org.apache.axis2.transport.http.util.RESTUtil.invokeAxisEngine(RESTUtil.java:136)
        at org.apache.axis2.transport.http.util.RESTUtil.processURLRequest(RESTUtil.java:130)
        at org.apache.axis2.transport.http.AxisServlet$RestRequestProcessor.processURLRequest(AxisServlet.java:829)
        at org.apache.axis2.transport.http.AxisServlet.doGet(AxisServlet.java:255)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:617)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
        at org.cmdbuild.filters.AuthFilter.doFilter(AuthFilter.java:29)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
        at org.cmdbuild.filters.PatchManagerFilter.doFilter(PatchManagerFilter.java:30)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
        at org.cmdbuild.filters.ConfCheckFilter.doFilter(ConfCheckFilter.java:31)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
        at org.cmdbuild.filters.TranslationFilter.doFilter(TranslationFilter.java:47)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
        at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
        at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
        at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:128)
        at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
        at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
        at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:293)
        at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:849)
        at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:583)
        at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:454)
        at java.lang.Thread.run(Thread.java:619)

E il messaggio intercettato dall'applicativo è il seguente:

Il contenuto della risposta rilevato dal client è di tipo 'text/html;charset=utf-8', invece del previsto 'text/xml'.
Richiesta non riuscita con messaggio di errore:
--
<html>
<head>
<title>Apache Tomcat/6.0.20 - Error report</title>
<style>
<!--H1 {font-family:Tahoma,Arial,sans-serif;color:white;background-color:#525D76;font-size:22px;}
H2 {font-family:Tahoma,Arial,sans-serif;color:white;background-color:#525D76;font-size:16px;}
H3 {font-family:Tahoma,Arial,sans-serif;color:white;background-color:#525D76;font-size:14px;}
BODY {font-family:Tahoma,Arial,sans-serif;color:black;background-color:white;}
B {font-family:Tahoma,Arial,sans-serif;color:white;background-color:#525D76;}
P {font-family:Tahoma,Arial,sans-serif;background:white;color:black;font-size:12px;}
A {color : black;}A.name {color : black;}HR {color : #525D76;}-->
</style>
</head>
<body>
<h1>HTTP Status 500 - </h1>
<HR size="1" noshade="noshade">
<p><b>type</b> Status report</p>
<p><b>message</b> <u></u></p>
<p><b>description</b> <u>The server encountered an internal error () that prevented it from fulfilling this request.</u>
</p>
<HR size="1" noshade="noshade">
<h3>Apache Tomcat/6.0.20</h3>
</body>
</html>
--.

Avete suggerimenti da darci per far interagire i due applicativi?

Un saluto,

Claudio

Ciao Claudio,

dando una occhiata al tuo codice, pare che non utilizzi per autenticarti lo standard Username Token. Dai log puoi vedere infatti l'errore "Incoming message does not contain required Security header".

Verifica i meccanismi utilizzati da .NET per l'utilizzo di questa specifica.

Per controllare la correttezza del messaggio SOAP inviato puoi utilizzare dei tool come TCPMon che si mettono in ascolto sul canale e visualizzano i messaggi inviati.

Giuseppe

 

Ciao Claudio,

avete poi risolto il problema? Se si, potresti postare la soluzione?
 
Grazie in anticipo

Ciao Mario,

il problema lo abbiamo risolto passando a Windows Comunication Foundation e, soprattutto, al framework 4.0; da tale versione del framework è difatti supportato il flag "allowInsecureTransport" che permette la comunicazione via http (e non https) con passaggio delle credenziali in chiaro.

Non ci è possibile postare l'intera soluzione in quanto consta di diversi file (è però basata su del codice pubblicato su MSDN),

ma il "nocciolo" di quanto accennatoti in precedenza è questo :

        public static Binding userNameTokenBinding()
        {
            HttpTransportBindingElement httpTransport = new HttpTransportBindingElement();

            // the transport security binding element will be configured to require a username token
            // transport provides security, if needed
            TransportSecurityBindingElement transportSecurity = new TransportSecurityBindingElement();
            transportSecurity.EndpointSupportingTokenParameters.SignedEncrypted.Add(new UsernameTokenParameters());

            // disable secure transport for now
            transportSecurity.AllowInsecureTransport = true;
            transportSecurity.IncludeTimestamp = false;
            httpTransport.MaxReceivedMessageSize = 20000000;
            MtomMessageEncodingBindingElement me = new MtomMessageEncodingBindingElement(MessageVersion.Soap12, Encoding.UTF8);
            //TextMessageEncodingBindingElement me = new TextMessageEncodingBindingElement(MessageVersion.Soap12, Encoding.UTF8);
            return new CustomBinding(transportSecurity, me,  httpTransport);
        }

Spero possa tornarti utile...

Ciao

Gianni

Ciao Gianni,

grazie per la risposta. 
Non sono molto pratico di WCF quindi dovrò prima cercare di capire come funziona, ma avere una strada da seguire è già qualcosa.
 
Ti farò sapere se riuscirò!
 

Ciao Gianni,

ho installato il VS2010 che supporta il framework4 ed ho creato una console application utilizzando le informazioni che mi hai dato:
Ecco il codice:
 
static void Main(string[] args)
        {
            try
            {
                EndpointAddress addr = new EndpointAddress("http://192.168.0.89:8080/cmdbuild/services/soap/Webservices");
                WServiceJAVA.WebservicesClient wsc = new ClientWCF.WServiceJAVA.WebservicesClient(userNameTokenBinding(), addr);
                wsc.ChannelFactory.Credentials.UserName.UserName = "admin";
                wsc.ChannelFactory.Credentials.UserName.Password = "admin";
                wsc.ClientCredentials.UserName.UserName = "admin";
                wsc.ClientCredentials.UserName.Password = "admin";

                //wsc.Open();
                wsc.getCardList("Pratica", null, null, null, 0, 0, "");
                wsc.Close();

                Console.WriteLine("FINE");
            }
            catch (Exception exc)
            {
                Console.WriteLine("EXCEPTION");
                Console.WriteLine(exc.Message);
            }
            int x = Console.Read();
        }

        public static Binding userNameTokenBinding()
        {
            //System.ServiceModel.Security.Tokens.UserNameSecurityTokenParameters UsernameTokenParameters 
            HttpTransportBindingElement httpTransport = new HttpTransportBindingElement();

            // the transport security binding element will be configured to require a username token
            // transport provides security, if needed
            TransportSecurityBindingElement transportSecurity = new TransportSecurityBindingElement();
            transportSecurity.EndpointSupportingTokenParameters.SignedEncrypted.Add(new UserNameSecurityTokenParameters());

            // disable secure transport for now
            transportSecurity.AllowInsecureTransport = true;
            transportSecurity.IncludeTimestamp = false;
            httpTransport.MaxReceivedMessageSize = 20000000;
            MtomMessageEncodingBindingElement me = new MtomMessageEncodingBindingElement(MessageVersion.Soap12, Encoding.UTF8);
            //TextMessageEncodingBindingElement me = new TextMessageEncodingBindingElement(MessageVersion.Soap12, Encoding.UTF8);
            return new CustomBinding(transportSecurity, me, httpTransport);
        } 
 
Ma quando provo ad eseguire, in debug, l'istruzione <wsc.getCardList("Pratica", null, null, null, 0, 0, "");>
mi va in eccezione. L'eccezione dice: <The security token could not be authenticated or authorized>
 
Hai qualche altro suggerimento? 
 
Scusa, dimenticavo di chiederti se potresti indicarmi anche l'articolo di MSDN che vi ha aiutato.
 
Grazie anticipatamente!
 

 

I had this problem and I managed to overcome that. (Tnx to Microsoft for such a good Help

)

1. Add Microsoft.Web.Services3.dll To your Project

2. Implement

IClientMessageInspector as bellow

 

   public class PasswordDigestMessageInspector : IClientMessageInspector

    {

        public string Username { get; set; }

        public string Password { get; set; }

 

        public PasswordDigestMessageInspector(string username, string password)

        {

            this.Username = username;

            this.Password = password;

        }

 

        public void AfterReceiveReply(ref System.ServiceModel.Channels.Message reply, object correlationState)

        {

            //throw new NotImplementedException();

        }

 

        public object BeforeSendRequest(ref System.ServiceModel.Channels.Message request, System.ServiceModel.IClientChannel channel)

        {

            // Use the WSE 3.0 security token class

            UsernameToken token = new UsernameToken(this.Username, this.Password, PasswordOption.SendHashed);

 

            // Serialize the token to XML

            XmlElement securityToken = token.GetXml(new XmlDocument());

 

            //

            MessageHeader securityHeader = MessageHeader.CreateHeader("Security", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd", securityToken, false);

            request.Headers.Add(securityHeader);

 

            // complete

            return Convert.DBNull;

        }

    }

 

3. Implement

IEndpointBehavior as below:

    public class PasswordDigestBehavior : IEndpointBehavior

    {

 

        public string Username { get; set; }

        public string Password { get; set; }

 

        public PasswordDigestBehavior(string username, string password)

        {

            this.Username = username;

            this.Password = password;

        }

 

        #region IEndpointBehavior Members

 

        public void AddBindingParameters(ServiceEndpoint endpoint, System.ServiceModel.Channels.BindingParameterCollection bindingParameters)

        {

            //throw new NotImplementedException();

        }

 

        public void ApplyClientBehavior(ServiceEndpoint endpoint, System.ServiceModel.Dispatcher.ClientRuntime clientRuntime)

        {

            clientRuntime.MessageInspectors.Add(new PasswordDigestMessageInspector(this.Username, this.Password));

        }

 

        public void ApplyDispatchBehavior(ServiceEndpoint endpoint, System.ServiceModel.Dispatcher.EndpointDispatcher endpointDispatcher)

        {

            //throw new NotImplementedException();

        }

 

        public void Validate(ServiceEndpoint endpoint)

        {

            //throw new NotImplementedException();

        }

 

        #endregion

    }

4. Config file:

 

<system.serviceModel>

    <bindings>

      <customBinding>

        <binding name="WebservicesImplServiceSoapBinding">

          <textMessageEncoding messageVersion="Soap12" />

          <security allowInsecureTransport="True" authenticationMode="UserNameOverTransport" ></security>

          <httpTransport />

        </binding>

      </customBinding>

    </bindings>

    <client>

      <endpoint address="http://192.168.1.1:8080/cmdb/services/soap/Webservices"

        binding="customBinding" bindingConfiguration="WebservicesImplServiceSoapBinding"

        contract="CMDBuildServices.Webservices" name="WebservicesImplPort" />

    </client>

  </system.serviceModel>

 

5. and then:

        static void Main(string[] args)

        {

            WebservicesClient client = new WebservicesClient();

            PasswordDigestBehavior behavior = new PasswordDigestBehavior("username", "password");

            client.Endpoint.Behaviors.Add(behavior);

 

            HttpTransportBindingElement httpTransport = new HttpTransportBindingElement();

            httpTransport.MaxReceivedMessageSize = 20000000;

            MtomMessageEncodingBindingElement me = new MtomMessageEncodingBindingElement(MessageVersion.Soap12, Encoding.UTF8);

            CustomBinding binding = new CustomBinding(me, httpTransport);

            client.Endpoint.Binding = binding;

 

            client.ClientCredentials.UserName.UserName = "username";

            client.ClientCredentials.UserName.Password = "password";

 

            cardList list = client.getCardList("TelecomCenter", null, null, null, 0, 0, "");

            Console.WriteLine(list.totalRows);

            Console.ReadKey();

        }

 

Previously Mario wrote:
Ciao Gianni,
ho installato il VS2010 che supporta il framework4 ed ho creato una console application utilizzando le informazioni che mi hai dato:
Ecco il codice:
 
static void Main(string[] args)
        {
            try
            {
                EndpointAddress addr = new EndpointAddress("http://192.168.0.89:8080/cmdbuild/services/soap/Webservices");
                WServiceJAVA.WebservicesClient wsc = new ClientWCF.WServiceJAVA.WebservicesClient(userNameTokenBinding(), addr);
                wsc.ChannelFactory.Credentials.UserName.UserName = "admin";
                wsc.ChannelFactory.Credentials.UserName.Password = "admin";
                wsc.ClientCredentials.UserName.UserName = "admin";
                wsc.ClientCredentials.UserName.Password = "admin";

                //wsc.Open();
                wsc.getCardList("Pratica", null, null, null, 0, 0, "");
                wsc.Close();

                Console.WriteLine("FINE");
            }
            catch (Exception exc)
            {
                Console.WriteLine("EXCEPTION");
                Console.WriteLine(exc.Message);
            }
            int x = Console.Read();
        }

        public static Binding userNameTokenBinding()
        {
            //System.ServiceModel.Security.Tokens.UserNameSecurityTokenParameters UsernameTokenParameters 
            HttpTransportBindingElement httpTransport = new HttpTransportBindingElement();

            // the transport security binding element will be configured to require a username token
            // transport provides security, if needed
            TransportSecurityBindingElement transportSecurity = new TransportSecurityBindingElement();
            transportSecurity.EndpointSupportingTokenParameters.SignedEncrypted.Add(new UserNameSecurityTokenParameters());

            // disable secure transport for now
            transportSecurity.AllowInsecureTransport = true;
            transportSecurity.IncludeTimestamp = false;
            httpTransport.MaxReceivedMessageSize = 20000000;
            MtomMessageEncodingBindingElement me = new MtomMessageEncodingBindingElement(MessageVersion.Soap12, Encoding.UTF8);
            //TextMessageEncodingBindingElement me = new TextMessageEncodingBindingElement(MessageVersion.Soap12, Encoding.UTF8);
            return new CustomBinding(transportSecurity, me, httpTransport);
        } 
 
Ma quando provo ad eseguire, in debug, l'istruzione <wsc.getCardList("Pratica", null, null, null, 0, 0, "");>
mi va in eccezione. L'eccezione dice: <The security token could not be authenticated or authorized>
 
Hai qualche altro suggerimento?