cancel
Showing results for 
Search instead for 
Did you mean: 

Accessing Alfresco WS through WCF ?

onewnan
Champ in-the-making
Champ in-the-making
.NET access is an important repository requirement for us at Policy Studies, Inc.  To test Alfresco's capabilities in this area I downloaded the dotnet WSE examples from http://forge.alfresco.com/projects/dotnet/.  However, I found that WSE requires configuration support which seems to be lacking VS 2008– according to http://forums.alfresco.com/en/viewtopic.php?f=27&t=5218.  Therefore I'm attempting to build a demo using WCF, as suggested in that posting, to accomodate current current .NET tooling and technology. 

I am surprised that I haven't found working WCF examples out on the Web or in the Alfresco toolkit.  Kindly let me know if
* I'm missing something in the way of working WCF examples
* there is any documentation for AlfrescoWS above and beyond the WSDL
* community and enterprise support the same WSDLs (am running community 2.1.0 at this point)

Having said that, here's a progress report so far trying to use WCF:

Using the attached ant task I was able to generate a file that compiles all services.  For this to work I first had to modify repository-service.wsdl, removing the nillable attributes for the two groups having ChildAssociation refs. 
Having done that, svcutil generates code.  It issues seemingly spurious error messages for some of the services of the form "The WSDL binding named XX is not valid because no match for operation YY was found in the corresponding portType definition."  However, it seems to generate interfaces and clients for all services.

While separate .cs files are generated for all services, it turns out authentication-service.cs contains interfaces for all of them.   I'm therefore feeding that one file to my .NET demo. 

The next step is to port pieces of the WSE demo–such as AuthenticationUtils and WebServicesFactory–to WCF.  I'll keep you posted…

attachment

============================



        …

   <property name="build.wcf.dir" location="DotNet/AlfrescoWS"/>
   <property name="wsdl.dir" location="DotNet/AlfrescoWS/wsdl"/>
         <property name="svcutil" location="C:/Program Files/Microsoft SDKs/Windows/v6.0A/Bin/SvcUtil.exe"/>

   <target name="genall"
      description="Using svcutil to generate stubs.">
      <exec executable="${svcutil}" dir="${wsdl.dir}">
         <arg value="/t:code" />
         <arg value="*.wsdl" />
         <arg value="*.xsd" />
         <arg value="/language:cs" />
         <arg value="/config:${build.wcf.dir}/output.config" />
         <arg value="/d:${build.wcf.dir}" />
         <arg value="/async" />
         <arg value="/targetClientVersion:Version30" />
      </exec>
   </target>

7 REPLIES 7

onewnan
Champ in-the-making
Champ in-the-making
At this point am churning with a security interoperability issue.  Am trying to reproduce in WCF the functionality of the following WSE code in dotnet2:

         
UsernameToken userToken = new UsernameToken(AuthenticationUtils.UserName, AuthenticationUtils.Ticket, (PasswordOption)2);
            service.RequestSoapContext.Security.Timestamp.TtlInSeconds = (long)300;
            service.RequestSoapContext.Security.Tokens.Add(userToken);

Have turned on SSL in Tomcat and am using 'tomcat' as user name (repository alias) with password of 'changeit' for all of: key store, tomcat users and Alfresco users.  The keystore password also is 'changeit'.

I am able to get the ticket from the authentication service but fail to access the repository service successfully with a getstores operation.  Attached are WCF trace records for the SOAP request and ensuing fault–"General security error       (WSSecurityEngine: Callback supplied no password for: tomcat)."   Any suggestions?  




<MessageLogTraceRecord
               Time="2008-07-18T05:52:52.0781250-06:00" Source="TransportSend"
               Type="System.ServiceModel.Security.SecurityAppliedMessage"
               xmlns="http://schemas.microsoft.com/2004/06/ServiceModel/Management/MessageTrace">
               <Addressing>
                  <Action>
                     http://www.alfresco.org/ws/service/repository/1.0/getStores
                  </Action>
                  <To>
                     https://localhost:8443/alfresco/api/RepositoryService
                  </To>
               </Addressing>
               <s:Envelope
                  xmlns:s="http://schemas.xmlsoap.org/soap/envelope/"
                  xmlns:u="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
                  <s:Header>
                     <o:Security s:mustUnderstand="1"
                        xmlns:o="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
                        <u:Timestamp u:Id="_0">
                           <u:Created>
                              2008-07-18T11:52:51.609Z
                           </u:Created>
                           <u:Expires>
                              2008-07-18T11:57:51.609Z
                           </u:Expires>
                        </u:Timestamp>
                        <o:UsernameToken
                           u:Id="uuid-8a9b624d-afb0-4efc-b29e-1fde338d91fc-2">
                           <o:Username><!–Removed–></o:Username>
                           <o:Password><!–Removed–></o:Password>
                        </o:UsernameToken>
                     </o:Security>
                  </s:Header>
                  <s:Body
                     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                     xmlns:xsd="http://www.w3.org/2001/XMLSchema">
                     <getStores
                        xmlns="http://www.alfresco.org/ws/service/repository/1.0">
                     </getStores>
                  </s:Body>
               </s:Envelope>
            </MessageLogTraceRecord>
         </DataItem>
      </TraceData>
   </ApplicationData>
</E2ETraceEvent>
<E2ETraceEvent
   xmlns="http://schemas.microsoft.com/2004/06/E2ETraceEvent">
   <System
      xmlns="http://schemas.microsoft.com/2004/06/windows/eventlog/system">
      <EventID>0</EventID>
      <Type>3</Type>
      <SubType Name="Information">0</SubType>
      <Level>8</Level>
      <TimeCreated SystemTime="2008-07-18T11:52:52.0937500Z" />
      <Source Name="System.ServiceModel.MessageLogging" />
      <Correlation
         ActivityID="{00000000-0000-0000-0000-000000000000}" />
      <Execution ProcessName="AlfrescoWS.vshost" ProcessID="368"
         ThreadID="10" />
      <Channel />
      <Computer>CODENV-L3B3320</Computer>
   </System>
   <ApplicationData>
      <TraceData>
         <DataItem>
            <MessageLogTraceRecord
               Time="2008-07-18T05:52:52.0937500-06:00" Source="TransportReceive"
               Type="System.ServiceModel.Channels.BufferedMessage"
               xmlns="http://schemas.microsoft.com/2004/06/ServiceModel/Management/MessageTrace">
               <HttpResponse>
                  <StatusCode>InternalServerError</StatusCode>
                  <StatusDescription>
                     Internal Server Error
                  </StatusDescription>
                  <WebHeaders>
                     <Transfer-Encoding>
                        chunked
                     </Transfer-Encoding>
                     <Connection>close</Connection>
                     <Content-Type>
                        text/xml;charset=utf-8
                     </Content-Type>
                     <Date>Fri, 18 Jul 2008 11:52:52 GMT</Date>
                     <Set-Cookie>
                        JSESSIONID=3B2228600B3AE4AEEBB2181E2E7864F7;
                        Path=/alfresco; Secure
                     </Set-Cookie>
                     <Server>Apache-Coyote/1.1</Server>
                  </WebHeaders>
               </HttpResponse>
               <soapenv:Envelope
                  xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
                  xmlns:xsd="http://www.w3.org/2001/XMLSchema"
                  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
                  <s:Header
                     xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
                  </s:Header>
                  <soapenv:Body>
                     <soapenv:Fault>
                        <faultcode xmlns="">
                           soapenv:Server.generalException
                        </faultcode>
                        <faultstring xmlns="">
                           WSDoAllReceiver: security processing
                           failed; nested exception is:
                           org.apache.ws.security.WSSecurityException:
                           General security error
                           (WSSecurityEngine: Callback supplied
                           no password for: tomcat)
                        </faultstring>
                        <detail xmlns="">
                           <ns1:hostname
                              xmlns:ns1="http://xml.apache.org/axis/">
                              CODENV-L3B3320
                           </ns1:hostname>
                        </detail>
                     </soapenv:Fault>
                  </soapenv:Body>
               </soapenv:Envelope>
            </MessageLogTraceRecord>

onewnan
Champ in-the-making
Champ in-the-making
As documented on the wiki the UserName SOAP header that Alfresco uses is based on an OASIS specification http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0.pdf.  Reading this I find that the 'password' field isn't necessarily or typically a simple password but rather a hash of several things (Password_Digest = Base64 ( SHA-1 ( nonce + created + password ) )).  Thus for grins I tried using the "ticket" as the "Password" and sure enough, Alfresco returns a getStores response.    However, the SOAP message seems to be absent a security header that WCF expects (SOAP header and partial stack trace are attached). 

Any suggestions?  I don't see anything in the OASIS spec requiring a SOAP header in the response.

attachments


System.ServiceModel.Security.MessageSecurityException: Security processor was un
able to find a security header in the message. This might be because the message
is an unsecured fault or because there is a binding mismatch between the commun
icating parties.   This can occur if the service is configured for security and
the client is not using security.

Server stack trace:
   at System.ServiceModel.Security.TransportSecurityProtocol.VerifyIncomingMessa
geCore(Message& message, TimeSpan timeout)
   at System.ServiceModel.Security.TransportSecurityProtocol.VerifyIncomingMessa
ge(Message& message, TimeSpan timeout)
   at System.ServiceModel.Security.SecurityProtocol.VerifyIncomingMessage(Messag
e& message, TimeSpan timeout, SecurityProtocolCorrelationState[] correlationStat
es)

onewnan
Champ in-the-making
Champ in-the-making
It turns out we can configure .NET not to use/expect timestamps; but in this case no timestamp is passed on invocation and Alfresco/Axis takes exception:


System.ServiceModel.FaultException:
WSDoAllReceiver: security processing failed (actions number mismatch)


Is there some we to configure Alfresco/Axis to use timestamps? 

I am under the impression Alfresco uses Axis due to when I get when attempting to open Web services pages in my browser.  However, I do not see the usual Axis artifacts like services.xml or the happy axis page.  What web services technology does Alfresco use and how can I configure options like timestamps?

onewnan
Champ in-the-making
Champ in-the-making
Problem summary:  Alfresco as shipped implements UsernameToken authentication expecting to receive the header in requests but not to return one in responses.  WCF expects to receive a UsernameToken header in the response if the request had one.

Workaround:  suppress this header to achieve interoperability.

C#:
            BindingElementCollection elements =   
                  service.Endpoint.Binding.CreateBindingElements();
            elements.Find<SecurityBindingElement>().IncludeTimestamp = false;
            service.Endpoint.Binding = new CustomBinding(elements);

Axis WSDD:

   <handler name="WSSecurity"
                 type="java:org.apache.ws.axis.security.WSDoAllReceiver">
      <!– parameter modified for WCF, was value="UsernameToken
                  Timestamp"   />–>
      <parameter name="action" value="UsernameToken"/>
   </handler>

onewnan
Champ in-the-making
Champ in-the-making
A couple more comments about this approach/workaround:

It breaks interoperability wih Al Fresco's client.   Perhaps the server could be enhanced to return a timestamp only when it receives one.  This apparently is only required for WSE interoperability anyhow, not compliance.

WCF insists on SSL when using the token.  This requires a a server cert, which can be prepared as discussed in server-config.wsdd.  WCF however doesn't trust that cert, but can be told to ignore it http://weblogs.asp.net/jan/archive/2003/12/04/41154.aspx.

The configuration I used for UserToken was


                  <security mode="TransportWithMessageCredential">
                    <transport clientCredentialType="None" proxyCredentialType="None" realm="" />
                    <message clientCredentialType="UserName" algorithmSuite="Default" />
                  </security>

garker
Champ in-the-making
Champ in-the-making
I got .Net connection to alfresco CMIS working.

I used the .Net WSE code from the other alfresco web services as a start.

You need to reference WSE 3.0, and the CMIS WSDL files.

Here is some code that works.


            // Init the CMIS Services
            reposvc = WebServiceFactory.getRepositoryService();
            obsvc = WebServiceFactory.getObjectService();
            navsvc = WebServiceFactory.getNavigationService();

            rep = reposvc.getRepositories();

            sRepositoryID = rep[0].repositoryID;

            sRepInfoType = reposvc.getRepositoryInfo(ref sRepositoryID, out sRel, out sDesc, out sVend,
                        out sProdName, out sProdVersion, out sRootFolderID, out repcap,
                        out sCmisVersions, out anyxml, out xmlelem);

trakhan
Champ in-the-making
Champ in-the-making
Ok,
have someone working example? I'd like to use WCF for webservice, but I found no working example. Sice I'm rather beginner to WCF concept solving all the issues byt myself is quite a task for me …