Chemistry
  1. Chemistry
  2. CMIS-450

CMIS Webservice binding cannot be connected if service URL is secured using Spring Basic Authentication

    Details

    • Type: Bug Bug
    • Status: Resolved
    • Priority: Major Major
    • Resolution: Not a Problem
    • Affects Version/s: OpenCMIS 0.5.0
    • Fix Version/s: None
    • Labels:
      None
    • Environment:

      Ubuntu Linux, JDK 1.6, Tomcat 6

      Description

      I am not able to establish the webservice binding which is mapped on the URL http://localhost:8080/contentservices/services/RepositoryService?wsdl that is authenticated via Spring Security (protected by basic Authentication). Following is the stack trace.

      org.apache.chemistry.opencmis.commons.exceptions.CmisConnectionException: Cannot initalize Web Services service object [org.apache.chemistry.opencmis.binding.webservices.RepositoryService]: XML reader error: com.ctc.wstx.exc.WstxParsingException: Unexpected close tag </td>; expected </input>.
      at [row,col,system-id]: [4,76,"http://localhost:8080/contentservices/services/RepositoryService?wsdl"]
      at org.apache.chemistry.opencmis.client.bindings.spi.webservices.AbstractPortProvider.initServiceObject(AbstractPortProvider.java:287)
      at org.apache.chemistry.opencmis.client.bindings.spi.webservices.AbstractPortProvider.getPortObject(AbstractPortProvider.java:205)
      at org.apache.chemistry.opencmis.client.bindings.spi.webservices.AbstractPortProvider.getRepositoryServicePort(AbstractPortProvider.java:108)
      at org.apache.chemistry.opencmis.client.bindings.spi.webservices.RepositoryServiceImpl.getRepositoryInfo(RepositoryServiceImpl.java:85)
      at org.apache.chemistry.opencmis.client.bindings.impl.RepositoryServiceImpl.getRepositoryInfo(RepositoryServiceImpl.java:69)
      at com.backbase.portal.contentservices.test.functional.WebServiceFunctionalTest.testWebServiceBinding(WebServiceFunctionalTest.java:57)
      at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
      at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
      at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
      at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:44)
      at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
      at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:41)
      at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)
      at org.junit.runners.BlockJUnit4ClassRunner.runNotIgnored(BlockJUnit4ClassRunner.java:79)
      at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:71)
      at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:49)
      at org.junit.runners.ParentRunner$3.run(ParentRunner.java:193)
      at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:52)
      at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:191)
      at org.junit.runners.ParentRunner.access$000(ParentRunner.java:42)
      at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:184)
      at org.junit.runners.ParentRunner.run(ParentRunner.java:236)
      at org.junit.runner.JUnitCore.run(JUnitCore.java:157)
      at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:71)
      at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:199)
      at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:62)
      at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
      at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
      at com.intellij.rt.execution.application.AppMain.main(AppMain.java:120)
      Caused by: com.sun.xml.ws.streaming.XMLStreamReaderException: XML reader error: com.ctc.wstx.exc.WstxParsingException: Unexpected close tag </td>; expected </input>.
      at [row,col,system-id]: [4,76,"http://localhost:8080/contentservices/services/RepositoryService?wsdl"]
      at com.sun.xml.ws.streaming.XMLStreamReaderUtil.wrapException(XMLStreamReaderUtil.java:267)
      at com.sun.xml.ws.streaming.XMLStreamReaderUtil.skipTags(XMLStreamReaderUtil.java:157)
      at com.sun.xml.ws.streaming.XMLStreamReaderUtil.skipElement(XMLStreamReaderUtil.java:130)
      at com.sun.xml.ws.wsdl.parser.WSDLParserExtensionFacade.definitionsElements(WSDLParserExtensionFacade.java:140)
      at com.sun.xml.ws.wsdl.parser.RuntimeWSDLParser.parseWSDL(RuntimeWSDLParser.java:325)
      at com.sun.xml.ws.wsdl.parser.RuntimeWSDLParser.parseUsingMex(RuntimeWSDLParser.java:207)
      at com.sun.xml.ws.wsdl.parser.RuntimeWSDLParser.tryWithMex(RuntimeWSDLParser.java:160)
      at com.sun.xml.ws.wsdl.parser.RuntimeWSDLParser.parse(RuntimeWSDLParser.java:138)
      at com.sun.xml.ws.client.WSServiceDelegate.parseWSDL(WSServiceDelegate.java:265)
      at com.sun.xml.ws.client.WSServiceDelegate.<init>(WSServiceDelegate.java:228)
      at com.sun.xml.ws.client.WSServiceDelegate.<init>(WSServiceDelegate.java:176)
      at com.sun.xml.ws.spi.ProviderImpl.createServiceDelegate(ProviderImpl.java:104)
      at javax.xml.ws.Service.<init>(Service.java:56)
      at org.apache.chemistry.opencmis.commons.impl.jaxb.RepositoryService.<init>(RepositoryService.java:42)
      at org.apache.chemistry.opencmis.client.bindings.spi.webservices.AbstractPortProvider.initServiceObject(AbstractPortProvider.java:253)
      ... 31 more
      Caused by: com.ctc.wstx.exc.WstxParsingException: Unexpected close tag </td>; expected </input>.
      at [row,col,system-id]: [4,76,"http://localhost:8080/contentservices/services/RepositoryService?wsdl"]
      at com.ctc.wstx.sr.StreamScanner.constructWfcException(StreamScanner.java:605)
      at com.ctc.wstx.sr.StreamScanner.throwParseError(StreamScanner.java:461)
      at com.ctc.wstx.sr.BasicStreamReader.reportWrongEndElem(BasicStreamReader.java:3256)
      at com.ctc.wstx.sr.BasicStreamReader.readEndElem(BasicStreamReader.java:3198)
      at com.ctc.wstx.sr.BasicStreamReader.nextFromTree(BasicStreamReader.java:2830)
      at com.ctc.wstx.sr.BasicStreamReader.next(BasicStreamReader.java:1019)
      at com.sun.xml.ws.util.xml.XMLStreamReaderFilter.next(XMLStreamReaderFilter.java:92)
      at com.sun.xml.ws.streaming.XMLStreamReaderUtil.skipTags(XMLStreamReaderUtil.java:146)
      ... 44 more

      We have the atom pub urls which are protected via the same Spring security basic authentication. And I am able to create the Atom Binding successfully but not Webservice binding.

        Activity

        Hide
        Florian Müller added a comment -

        Are you sure that http://localhost:8080/contentservices/services/RepositoryService?wsdl returns a WSDL? It seems to return a HTML page.
        If it is WSDL, why is it protected?

        See also: https://issues.apache.org/jira/browse/CMIS-423

        Show
        Florian Müller added a comment - Are you sure that http://localhost:8080/contentservices/services/RepositoryService?wsdl returns a WSDL? It seems to return a HTML page. If it is WSDL, why is it protected? See also: https://issues.apache.org/jira/browse/CMIS-423
        Hide
        Sanjay Bahrani added a comment -

        Thanks for quick feedback.

        This returns the WSDL if the user is authenticated using Spring basic authentication. If not it is redirected to page login page hence it returns the parsing exception.

        I looked it into the CMIS-423 where you recommended either to exclude the WSDL urls or implement the work around of Authenticator. I want to try this before I exclude the URL's. With reference to that I tried setting Authenticator.setDefault(new BasicAuthenticator(..)..) but it still gives me the same error.

        Show
        Sanjay Bahrani added a comment - Thanks for quick feedback. This returns the WSDL if the user is authenticated using Spring basic authentication. If not it is redirected to page login page hence it returns the parsing exception. I looked it into the CMIS-423 where you recommended either to exclude the WSDL urls or implement the work around of Authenticator. I want to try this before I exclude the URL's. With reference to that I tried setting Authenticator.setDefault(new BasicAuthenticator(..)..) but it still gives me the same error.
        Hide
        Florian Müller added a comment -

        If the server doesn't return the HTTP status code 401 (as it should) and instead redirects to a login page, the Authenticator isn't triggered and therefore the request is not authenticated.
        Can you reconfigure the server to return the status code 401?

        Show
        Florian Müller added a comment - If the server doesn't return the HTTP status code 401 (as it should) and instead redirects to a login page, the Authenticator isn't triggered and therefore the request is not authenticated. Can you reconfigure the server to return the status code 401?
        Hide
        Sanjay Bahrani added a comment -

        Correct me if i am wrong.. Does it mean I have to install Authenticator on server side. I am installing Authenticator when I was trying to cretae the webservice binding on the client side. like below:

        Map<String, String> parameters = new HashMap<String, String> ();

        parameters.put(SessionParameter.USER, "admin");
        parameters.put(SessionParameter.PASSWORD, "admin");
        parameters.put(SessionParameter.WEBSERVICES_REPOSITORY_SERVICE, repositoryServiceWsdlUrl);
        parameters.put(SessionParameter.WEBSERVICES_NAVIGATION_SERVICE, navigationServiceWsdlUrl);
        parameters.put(SessionParameter.WEBSERVICES_OBJECT_SERVICE, objectServiceWsdlUrl);
        parameters.put(SessionParameter.WEBSERVICES_VERSIONING_SERVICE, versioningServiceWsdlUrl);
        parameters.put(SessionParameter.WEBSERVICES_DISCOVERY_SERVICE, discoveryServiceWsdlUrl);
        parameters.put(SessionParameter.WEBSERVICES_RELATIONSHIP_SERVICE, relationshipServiceWsdlUrl);
        parameters.put(SessionParameter.WEBSERVICES_MULTIFILING_SERVICE, multiFilingServiceWsdlUrl);
        parameters.put(SessionParameter.WEBSERVICES_POLICY_SERVICE, policyServiceWsdlUrl);
        parameters.put(SessionParameter.WEBSERVICES_ACL_SERVICE, aclServiceWsdlUrl);

        Authenticator.setDefault(new BasicAuthenticator("admin", "admin"));
        CmisBindingFactory factory = CmisBindingFactory.newInstance();
        CmisBinding binding = factory.createCmisWebServicesBinding(parameters);
        Assert.notNull(binding);
        RepositoryInfo contentRepository = binding.getRepositoryService().getRepositoryInfo(..);
        Assert.notNull(contentRepository);

        Show
        Sanjay Bahrani added a comment - Correct me if i am wrong.. Does it mean I have to install Authenticator on server side. I am installing Authenticator when I was trying to cretae the webservice binding on the client side. like below: Map<String, String> parameters = new HashMap<String, String> (); parameters.put(SessionParameter.USER, "admin"); parameters.put(SessionParameter.PASSWORD, "admin"); parameters.put(SessionParameter.WEBSERVICES_REPOSITORY_SERVICE, repositoryServiceWsdlUrl); parameters.put(SessionParameter.WEBSERVICES_NAVIGATION_SERVICE, navigationServiceWsdlUrl); parameters.put(SessionParameter.WEBSERVICES_OBJECT_SERVICE, objectServiceWsdlUrl); parameters.put(SessionParameter.WEBSERVICES_VERSIONING_SERVICE, versioningServiceWsdlUrl); parameters.put(SessionParameter.WEBSERVICES_DISCOVERY_SERVICE, discoveryServiceWsdlUrl); parameters.put(SessionParameter.WEBSERVICES_RELATIONSHIP_SERVICE, relationshipServiceWsdlUrl); parameters.put(SessionParameter.WEBSERVICES_MULTIFILING_SERVICE, multiFilingServiceWsdlUrl); parameters.put(SessionParameter.WEBSERVICES_POLICY_SERVICE, policyServiceWsdlUrl); parameters.put(SessionParameter.WEBSERVICES_ACL_SERVICE, aclServiceWsdlUrl); Authenticator.setDefault(new BasicAuthenticator("admin", "admin")); CmisBindingFactory factory = CmisBindingFactory.newInstance(); CmisBinding binding = factory.createCmisWebServicesBinding(parameters); Assert.notNull(binding); RepositoryInfo contentRepository = binding.getRepositoryService().getRepositoryInfo(..); Assert.notNull(contentRepository);
        Hide
        Florian Müller added a comment -

        No, the Authenticator has to be at the client side - exactly as you did it. But it is only used if the server returns the status code 401 when the client tries to access the WSDL. Your server does return a HTML page instead (I assume with the status code 200). Therefore, the client never sends the credentials to server. As long as the server does not return the right status code (401), you will not be able to fetch the WSDL.
        The alternative is not to protect the WSDL at all.

        Show
        Florian Müller added a comment - No, the Authenticator has to be at the client side - exactly as you did it. But it is only used if the server returns the status code 401 when the client tries to access the WSDL. Your server does return a HTML page instead (I assume with the status code 200). Therefore, the client never sends the credentials to server. As long as the server does not return the right status code (401), you will not be able to fetch the WSDL. The alternative is not to protect the WSDL at all.
        Hide
        Sanjay Bahrani added a comment -

        Ok.. Let me try this. Thanks for your feedback.

        Another question came poping up how does the atom pub works? as I have similar configuration (Spring secutiry Basic Authentication) for atom (http://localhost:8080/contentservices/atom) as well. But then using client api I am able to create the Atom binding. Conceptually both the webservices and atom urls are secured via same configurations

        Show
        Sanjay Bahrani added a comment - Ok.. Let me try this. Thanks for your feedback. Another question came poping up how does the atom pub works? as I have similar configuration (Spring secutiry Basic Authentication) for atom ( http://localhost:8080/contentservices/atom ) as well. But then using client api I am able to create the Atom binding. Conceptually both the webservices and atom urls are secured via same configurations
        Hide
        Sanjay Bahrani added a comment -

        I took your suggestion and made the WSDL URL nor protected. I have another question what if I want to implement the security on method calls via web service binding. Does open cmis support that?

        Show
        Sanjay Bahrani added a comment - I took your suggestion and made the WSDL URL nor protected. I have another question what if I want to implement the security on method calls via web service binding. Does open cmis support that?
        Hide
        Florian Müller added a comment -

        OpenCMIS supports WS-Security UsernameToken (recommended by the CMIS spec) and basic authentication out-of-the-box. Other authentication mechanisms can be plugged in.

        Show
        Florian Müller added a comment - OpenCMIS supports WS-Security UsernameToken (recommended by the CMIS spec) and basic authentication out-of-the-box. Other authentication mechanisms can be plugged in.
        Hide
        Sanjay Bahrani added a comment -

        Can you please elaborate further.. I want to have messages secured with Username token.

        Show
        Sanjay Bahrani added a comment - Can you please elaborate further.. I want to have messages secured with Username token.
        Hide
        Florian Müller added a comment -

        There is not much to consider. The client has to send a UsernameToken SOAP header. An OpenCMIS based client does that automatically when you add a username and a password to the session parameters (see [1]). On the server side OpenCMIS extracts the username and the password and provides them in the CallContext [2] object. All you have to do is to validate these credentials.
        (Btw. Please ask questions on the mailing list.)

        [1] http://chemistry.apache.org/java/examples/example-create-session.html
        [2] http://chemistry.apache.org/java/0.6.0/maven/apidocs/org/apache/chemistry/opencmis/commons/server/CallContext.html

        Show
        Florian Müller added a comment - There is not much to consider. The client has to send a UsernameToken SOAP header. An OpenCMIS based client does that automatically when you add a username and a password to the session parameters (see [1] ). On the server side OpenCMIS extracts the username and the password and provides them in the CallContext [2] object. All you have to do is to validate these credentials. (Btw. Please ask questions on the mailing list.) [1] http://chemistry.apache.org/java/examples/example-create-session.html [2] http://chemistry.apache.org/java/0.6.0/maven/apidocs/org/apache/chemistry/opencmis/commons/server/CallContext.html
        Hide
        shaoyuliang added a comment -

        If you choose open the url in the browser ,it may popup the dialog and ask you to login with the right username and password . And then your http request may contains the authorization header . I think this error due to the response of your url , you may have implemented the wrong response in the xml body?

        Show
        shaoyuliang added a comment - If you choose open the url in the browser ,it may popup the dialog and ask you to login with the right username and password . And then your http request may contains the authorization header . I think this error due to the response of your url , you may have implemented the wrong response in the xml body?

          People

          • Assignee:
            Unassigned
            Reporter:
            Sanjay Bahrani
          • Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved:

              Development