You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@chemistry.apache.org by fm...@apache.org on 2015/08/12 17:15:58 UTC
svn commit: r1695555 - in
/chemistry/opencmis/trunk/chemistry-opencmis-server:
chemistry-opencmis-server-bindings-war/src/main/webapp/WEB-INF/
chemistry-opencmis-server-bindings/src/main/java/org/apache/chemistry/opencmis/server/impl/
chemistry-opencmi...
Author: fmui
Date: Wed Aug 12 15:15:57 2015
New Revision: 1695555
URL: http://svn.apache.org/r1695555
Log:
CMIS-914: added server part (CMIS Endpoint Documents and CSRF protection)
Added:
chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings-war/src/main/webapp/WEB-INF/cmis-endpoints.json
chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings/src/main/java/org/apache/chemistry/opencmis/server/impl/endpoints/
chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings/src/main/java/org/apache/chemistry/opencmis/server/impl/endpoints/AbstractCmisEndpointsDocumentServlet.java
chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings/src/main/java/org/apache/chemistry/opencmis/server/impl/endpoints/SimpleCmisEndpointsDocumentServlet.java
chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings/src/main/java/org/apache/chemistry/opencmis/server/shared/CsrfManager.java
Modified:
chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings-war/src/main/webapp/WEB-INF/web.xml
chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings/src/main/java/org/apache/chemistry/opencmis/server/impl/CmisRepositoryContextListener.java
chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings/src/main/java/org/apache/chemistry/opencmis/server/impl/atompub/CmisAtomPubServlet.java
chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings/src/main/java/org/apache/chemistry/opencmis/server/impl/browser/CmisBrowserBindingServlet.java
chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings/src/main/java/org/apache/chemistry/opencmis/server/impl/browser/token/AbstractSimpleTokenHandler.java
chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings/src/main/java/org/apache/chemistry/opencmis/server/impl/webservices/AbstractService.java
chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings/src/main/java/org/apache/chemistry/opencmis/server/impl/webservices/CmisWebServicesServlet.java
chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings/src/main/java/org/apache/chemistry/opencmis/server/impl/webservices/RepositoryService.java
chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings/src/main/java/org/apache/chemistry/opencmis/server/shared/AbstractCmisHttpServlet.java
Added: chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings-war/src/main/webapp/WEB-INF/cmis-endpoints.json
URL: http://svn.apache.org/viewvc/chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings-war/src/main/webapp/WEB-INF/cmis-endpoints.json?rev=1695555&view=auto
==============================================================================
--- chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings-war/src/main/webapp/WEB-INF/cmis-endpoints.json (added)
+++ chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings-war/src/main/webapp/WEB-INF/cmis-endpoints.json Wed Aug 12 15:15:57 2015
@@ -0,0 +1,84 @@
+{
+ "endpoints": [
+ {
+ "displayName": "OpenCMIS CMIS 1.0 AtomPub Binding",
+ "binding": "atompub",
+ "cmisVersion": "1.0",
+ "cookies": "optional",
+ "compression": "server",
+ "url": "{webapp}/atom",
+ "authentication": [
+ {
+ "displayName": "HTTP basic authentication",
+ "type": "basic",
+ "preference": 4,
+ "documentationUrl": "https://chemistry.apache.org/java/opencmis.html"
+ }
+ ]
+ },
+ {
+ "displayName": "OpenCMIS CMIS 1.1 AtomPub Binding",
+ "binding": "atompub",
+ "cmisVersion": "1.1",
+ "cookies": "optional",
+ "compression": "server",
+ "url": "{webapp}/atom11",
+ "authentication": [
+ {
+ "displayName": "HTTP basic authentication",
+ "type": "basic",
+ "preference": 2,
+ "documentationUrl": "https://chemistry.apache.org/java/opencmis.html"
+ }
+ ]
+ },
+ {
+ "displayName": "OpenCMIS CMIS 1.0 Web Services Binding",
+ "binding": "webservices",
+ "cmisVersion": "1.0",
+ "cookies": "optional",
+ "compression": "server",
+ "url": "{webapp}/services/cmis?wsdl ",
+ "authentication": [
+ {
+ "displayName": "UsernameToken authentication",
+ "type": "usernameToken",
+ "preference": 5,
+ "documentationUrl": "https://chemistry.apache.org/java/opencmis.html"
+ }
+ ]
+ },
+ {
+ "displayName": "OpenCMIS CMIS 1.1 Web Services Binding",
+ "binding": "webservices",
+ "cmisVersion": "1.1",
+ "cookies": "optional",
+ "compression": "server",
+ "url": "{webapp}/services11/cmis?wsdl ",
+ "authentication": [
+ {
+ "displayName": "UsernameToken authentication",
+ "type": "usernameToken",
+ "preference": 3,
+ "documentationUrl": "https://chemistry.apache.org/java/opencmis.html"
+ }
+ ]
+ },
+ {
+ "displayName": "OpenCMIS CMIS 1.1 Browser Binding",
+ "binding": "browser",
+ "cmisVersion": "1.1",
+ "cookies": "optional",
+ "compression": "server",
+ "url": "{webapp}/browser",
+ "authentication": [
+ {
+ "displayName": "HTTP basic authentication",
+ "type": "basic",
+ "preference": 1,
+ "documentationUrl": "https://chemistry.apache.org/java/opencmis.html"
+ }
+ ]
+ }
+ ]
+}
\ No newline at end of file
Modified: chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings-war/src/main/webapp/WEB-INF/web.xml
URL: http://svn.apache.org/viewvc/chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings-war/src/main/webapp/WEB-INF/web.xml?rev=1695555&r1=1695554&r2=1695555&view=diff
==============================================================================
--- chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings-war/src/main/webapp/WEB-INF/web.xml (original)
+++ chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings-war/src/main/webapp/WEB-INF/web.xml Wed Aug 12 15:15:57 2015
@@ -112,7 +112,7 @@
<!--
Uncomment the following filter to enable CORS support for the browser binding.
See http://software.dzhuvinov.com/cors-filter.html for details.
- Put the CORS libraries into the WEB-INF/lib directory or uncomment the CORS depenedency in the pom.xml.
+ Put the CORS libraries into the WEB-INF/lib directory or uncomment the CORS dependency in the pom.xml.
-->
<!--
<filter>
@@ -219,6 +219,16 @@
</init-param>
<load-on-startup>2</load-on-startup>
</servlet>
+
+ <servlet>
+ <servlet-name>cmisendpoints</servlet-name>
+ <servlet-class>org.apache.chemistry.opencmis.server.impl.endpoints.SimpleCmisEndpointsDocumentServlet</servlet-class>
+ <init-param>
+ <param-name>template</param-name>
+ <param-value>/WEB-INF/cmis-endpoints.json</param-value>
+ </init-param>
+ <load-on-startup>3</load-on-startup>
+ </servlet>
<servlet-mapping>
<servlet-name>cmisws10</servlet-name>
@@ -244,4 +254,9 @@
<servlet-name>cmisbrowser</servlet-name>
<url-pattern>/browser/*</url-pattern>
</servlet-mapping>
+
+ <servlet-mapping>
+ <servlet-name>cmisendpoints</servlet-name>
+ <url-pattern>/cmis-endpoints.json</url-pattern>
+ </servlet-mapping>
</web-app>
Modified: chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings/src/main/java/org/apache/chemistry/opencmis/server/impl/CmisRepositoryContextListener.java
URL: http://svn.apache.org/viewvc/chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings/src/main/java/org/apache/chemistry/opencmis/server/impl/CmisRepositoryContextListener.java?rev=1695555&r1=1695554&r2=1695555&view=diff
==============================================================================
--- chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings/src/main/java/org/apache/chemistry/opencmis/server/impl/CmisRepositoryContextListener.java (original)
+++ chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings/src/main/java/org/apache/chemistry/opencmis/server/impl/CmisRepositoryContextListener.java Wed Aug 12 15:15:57 2015
@@ -25,6 +25,7 @@ import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
+import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
@@ -47,6 +48,7 @@ public class CmisRepositoryContextListen
private static final String CONFIG_FILENAME = "/repository.properties";
private static final String PROPERTY_CLASS = "class";
+ @Override
public void contextInitialized(ServletContextEvent sce) {
// get config file name or use default
String configFilename = sce.getServletContext().getInitParameter(CONFIG_INIT_PARAM);
@@ -67,6 +69,7 @@ public class CmisRepositoryContextListen
sce.getServletContext().setAttribute(SERVICES_FACTORY, factory);
}
+ @Override
public void contextDestroyed(ServletContextEvent sce) {
// destroy services factory
CmisServiceFactory factory = (CmisServiceFactory) sce.getServletContext().getAttribute(SERVICES_FACTORY);
@@ -81,6 +84,13 @@ public class CmisRepositoryContextListen
}
/**
+ * Gets the service factory from the servlet context.
+ */
+ public static CmisServiceFactory getServiceFactory(final ServletContext servletContext) {
+ return (CmisServiceFactory) servletContext.getAttribute(SERVICES_FACTORY);
+ }
+
+ /**
* Creates a service factory.
*/
private CmisServiceFactory createServiceFactory(String filename) {
Modified: chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings/src/main/java/org/apache/chemistry/opencmis/server/impl/atompub/CmisAtomPubServlet.java
URL: http://svn.apache.org/viewvc/chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings/src/main/java/org/apache/chemistry/opencmis/server/impl/atompub/CmisAtomPubServlet.java?rev=1695555&r1=1695554&r2=1695555&view=diff
==============================================================================
--- chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings/src/main/java/org/apache/chemistry/opencmis/server/impl/atompub/CmisAtomPubServlet.java (original)
+++ chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings/src/main/java/org/apache/chemistry/opencmis/server/impl/atompub/CmisAtomPubServlet.java Wed Aug 12 15:15:57 2015
@@ -170,6 +170,11 @@ public class CmisAtomPubServlet extends
CallContext context = null;
try {
+ // CSRF token check
+ if (!METHOD_GET.equals(request.getMethod()) && !METHOD_HEAD.equals(request.getMethod())) {
+ checkCsrfToken(request, response, false, false);
+ }
+
// split path
String[] pathFragments = HttpUtils.splitPath(request);
@@ -235,6 +240,9 @@ public class CmisAtomPubServlet extends
// analyze the path
if (pathFragments.length < 2) {
+ // CSRF check
+ checkCsrfToken(request, response, true, false);
+
// root -> service document
dispatcher.dispatch("", METHOD_GET, context, service, null, request, response);
return;
@@ -244,6 +252,9 @@ public class CmisAtomPubServlet extends
String repositoryId = pathFragments[0];
String resource = pathFragments[1];
+ // CSRF check
+ checkCsrfToken(request, response, false, RESOURCE_CONTENT.equals(resource) && METHOD_GET.equals(method));
+
// dispatch
boolean callServiceFound = dispatcher.dispatch(resource, method, context, service, repositoryId, request,
response);
Modified: chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings/src/main/java/org/apache/chemistry/opencmis/server/impl/browser/CmisBrowserBindingServlet.java
URL: http://svn.apache.org/viewvc/chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings/src/main/java/org/apache/chemistry/opencmis/server/impl/browser/CmisBrowserBindingServlet.java?rev=1695555&r1=1695554&r2=1695555&view=diff
==============================================================================
--- chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings/src/main/java/org/apache/chemistry/opencmis/server/impl/browser/CmisBrowserBindingServlet.java (original)
+++ chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings/src/main/java/org/apache/chemistry/opencmis/server/impl/browser/CmisBrowserBindingServlet.java Wed Aug 12 15:15:57 2015
@@ -215,6 +215,12 @@ public class CmisBrowserBindingServlet e
CallContext context = null;
try {
+ // CSRF token check
+ String method = request.getMethod();
+ if (!METHOD_GET.equals(method) && !METHOD_HEAD.equals(method)) {
+ checkCsrfToken(request, response, false, false);
+ }
+
// set default headers
response.addHeader("Cache-Control", "private, max-age=0");
response.addHeader("Server", ServerVersion.OPENCMIS_SERVER);
@@ -227,8 +233,6 @@ public class CmisBrowserBindingServlet e
pathFragments.length > 0 ? pathFragments[0] : null);
// check HTTP method
- String method = request.getMethod();
-
if (METHOD_GET.equals(method)) {
request = new QueryStringHttpServletRequestWrapper(request);
} else if (METHOD_POST.equals(method)) {
@@ -310,6 +314,9 @@ public class CmisBrowserBindingServlet e
// analyze the path
if (pathFragments.length < 1) {
+ // CSRF check
+ checkCsrfToken(request, response, true, false);
+
// root -> repository infos
repositoryDispatcher.dispatch("", METHOD_GET, context, service, null, request, response);
return;
@@ -341,6 +348,10 @@ public class CmisBrowserBindingServlet e
throw new CmisNotSupportedException("No selector");
}
+ // CSRF check
+ checkCsrfToken(request, response, SELECTOR_REPOSITORY_INFO.equalsIgnoreCase(selector), false);
+
+ // dispatch
browserContext.setCallDetails(service, objectId, null, null);
callServiceFound = repositoryDispatcher.dispatch(selector, method, browserContext, service,
repositoryId, request, response);
@@ -367,6 +378,10 @@ public class CmisBrowserBindingServlet e
}
}
+ // CSRF check
+ checkCsrfToken(request, response, false, SELECTOR_CONTENT.equalsIgnoreCase(selector));
+
+ // dispatch
callServiceFound = rootDispatcher.dispatch(selector, method, browserContext, service, repositoryId,
request, response);
}
Modified: chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings/src/main/java/org/apache/chemistry/opencmis/server/impl/browser/token/AbstractSimpleTokenHandler.java
URL: http://svn.apache.org/viewvc/chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings/src/main/java/org/apache/chemistry/opencmis/server/impl/browser/token/AbstractSimpleTokenHandler.java?rev=1695555&r1=1695554&r2=1695555&view=diff
==============================================================================
--- chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings/src/main/java/org/apache/chemistry/opencmis/server/impl/browser/token/AbstractSimpleTokenHandler.java (original)
+++ chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings/src/main/java/org/apache/chemistry/opencmis/server/impl/browser/token/AbstractSimpleTokenHandler.java Wed Aug 12 15:15:57 2015
@@ -331,8 +331,7 @@ public abstract class AbstractSimpleToke
}
protected CmisServiceFactory getCmisServiceFactory(final ServletContext servletContext) {
- CmisServiceFactory factory = (CmisServiceFactory) servletContext
- .getAttribute(CmisRepositoryContextListener.SERVICES_FACTORY);
+ CmisServiceFactory factory = CmisRepositoryContextListener.getServiceFactory(servletContext);
if (factory == null) {
throw new CmisRuntimeException("Service factory not available! Configuration problem?");
Added: chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings/src/main/java/org/apache/chemistry/opencmis/server/impl/endpoints/AbstractCmisEndpointsDocumentServlet.java
URL: http://svn.apache.org/viewvc/chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings/src/main/java/org/apache/chemistry/opencmis/server/impl/endpoints/AbstractCmisEndpointsDocumentServlet.java?rev=1695555&view=auto
==============================================================================
--- chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings/src/main/java/org/apache/chemistry/opencmis/server/impl/endpoints/AbstractCmisEndpointsDocumentServlet.java (added)
+++ chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings/src/main/java/org/apache/chemistry/opencmis/server/impl/endpoints/AbstractCmisEndpointsDocumentServlet.java Wed Aug 12 15:15:57 2015
@@ -0,0 +1,84 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.chemistry.opencmis.server.impl.endpoints;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.PrintWriter;
+import java.io.Reader;
+import java.net.URL;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.chemistry.opencmis.commons.endpoints.CmisEndpointsDocument;
+import org.apache.chemistry.opencmis.commons.impl.endpoints.CmisEndpointsDocumentHelper;
+import org.apache.chemistry.opencmis.commons.impl.json.parser.JSONParseException;
+
+/**
+ * Serves the CMIS Endpoints Document.
+ */
+public abstract class AbstractCmisEndpointsDocumentServlet extends HttpServlet {
+
+ private static final long serialVersionUID = 1L;
+
+ @Override
+ protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
+
+ CmisEndpointsDocument doc = getCmisEndpointsDocument(req, resp);
+ if (doc == null) {
+ resp.sendError(HttpServletResponse.SC_NOT_FOUND, "CMIS Endpoints Document is not available!");
+ return;
+ }
+
+ resp.setContentType("application/json; charset=UTF-8");
+
+ PrintWriter pw = resp.getWriter();
+ CmisEndpointsDocumentHelper.write(doc, pw);
+ }
+
+ /**
+ * Returns a CMIS Endpoints Document.
+ */
+ public abstract CmisEndpointsDocument getCmisEndpointsDocument(HttpServletRequest req, HttpServletResponse resp)
+ throws ServletException;
+
+ public CmisEndpointsDocument readCmisEndpointsDocument(URL url) throws IOException, JSONParseException {
+ return CmisEndpointsDocumentHelper.read(url);
+ }
+
+ public CmisEndpointsDocument readCmisEndpointsDocument(File file) throws IOException, JSONParseException {
+ return CmisEndpointsDocumentHelper.read(file);
+ }
+
+ public CmisEndpointsDocument readCmisEndpointsDocument(InputStream in) throws IOException, JSONParseException {
+ return CmisEndpointsDocumentHelper.read(in);
+ }
+
+ public CmisEndpointsDocument readCmisEndpointsDocument(Reader in) throws IOException, JSONParseException {
+ return CmisEndpointsDocumentHelper.read(in);
+ }
+
+ public CmisEndpointsDocument readCmisEndpointsDocument(String in) throws JSONParseException {
+ return CmisEndpointsDocumentHelper.read(in);
+ }
+}
Added: chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings/src/main/java/org/apache/chemistry/opencmis/server/impl/endpoints/SimpleCmisEndpointsDocumentServlet.java
URL: http://svn.apache.org/viewvc/chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings/src/main/java/org/apache/chemistry/opencmis/server/impl/endpoints/SimpleCmisEndpointsDocumentServlet.java?rev=1695555&view=auto
==============================================================================
--- chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings/src/main/java/org/apache/chemistry/opencmis/server/impl/endpoints/SimpleCmisEndpointsDocumentServlet.java (added)
+++ chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings/src/main/java/org/apache/chemistry/opencmis/server/impl/endpoints/SimpleCmisEndpointsDocumentServlet.java Wed Aug 12 15:15:57 2015
@@ -0,0 +1,69 @@
+package org.apache.chemistry.opencmis.server.impl.endpoints;
+
+import java.io.InputStream;
+
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.chemistry.opencmis.commons.endpoints.CmisEndpointsDocument;
+import org.apache.chemistry.opencmis.commons.impl.IOUtils;
+import org.apache.chemistry.opencmis.commons.impl.UrlBuilder;
+import org.apache.chemistry.opencmis.commons.impl.json.parser.JSONParseException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * A simple CMIS Endpoints Document servlet.
+ *
+ * It reads an endpoints document from a file replace some strings.
+ */
+public class SimpleCmisEndpointsDocumentServlet extends AbstractCmisEndpointsDocumentServlet {
+
+ private static final long serialVersionUID = 1L;
+ private static final Logger LOG = LoggerFactory.getLogger(SimpleCmisEndpointsDocumentServlet.class);
+
+ private static final String PARAM_ENDPOINT_TEMPLATE = "template";
+
+ private String endpointsDocument;
+
+ @Override
+ public void init(ServletConfig config) throws ServletException {
+ super.init(config);
+
+ String template = config.getInitParameter(PARAM_ENDPOINT_TEMPLATE);
+ if (template == null) {
+ LOG.error("CMIS Endpoints Document template provided!");
+ return;
+ }
+
+ // load template from file
+ try {
+ InputStream stream = config.getServletContext().getResourceAsStream(template);
+ if (stream != null) {
+ endpointsDocument = IOUtils.readAllLines(stream);
+ }
+ } catch (Exception e) {
+ LOG.error("Could not read CMIS Endpoints Document template from {}!", template, e);
+ }
+ }
+
+ @Override
+ public CmisEndpointsDocument getCmisEndpointsDocument(HttpServletRequest req, HttpServletResponse resp) {
+ if (endpointsDocument == null) {
+ // we don't have a template
+ return null;
+ }
+
+ UrlBuilder url = new UrlBuilder(req.getScheme(), req.getServerName(), req.getServerPort(), null);
+ url.addPath(req.getContextPath());
+
+ try {
+ return readCmisEndpointsDocument(endpointsDocument.replaceAll("\\{webapp\\}", url.toString()));
+ } catch (JSONParseException e) {
+ LOG.error("Invalid JSON!", e);
+ return null;
+ }
+ }
+}
Modified: chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings/src/main/java/org/apache/chemistry/opencmis/server/impl/webservices/AbstractService.java
URL: http://svn.apache.org/viewvc/chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings/src/main/java/org/apache/chemistry/opencmis/server/impl/webservices/AbstractService.java?rev=1695555&r1=1695554&r2=1695555&view=diff
==============================================================================
--- chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings/src/main/java/org/apache/chemistry/opencmis/server/impl/webservices/AbstractService.java (original)
+++ chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings/src/main/java/org/apache/chemistry/opencmis/server/impl/webservices/AbstractService.java Wed Aug 12 15:15:57 2015
@@ -55,6 +55,7 @@ import org.apache.chemistry.opencmis.com
import org.apache.chemistry.opencmis.server.impl.CallContextImpl;
import org.apache.chemistry.opencmis.server.impl.CmisRepositoryContextListener;
import org.apache.chemistry.opencmis.server.impl.ServerVersion;
+import org.apache.chemistry.opencmis.server.shared.CsrfManager;
import org.apache.chemistry.opencmis.server.shared.ExceptionHelper;
import org.apache.chemistry.opencmis.server.shared.TempStoreOutputStreamFactory;
import org.slf4j.Logger;
@@ -78,8 +79,7 @@ public abstract class AbstractService {
MessageContext.SERVLET_CONTEXT);
// get services factory
- CmisServiceFactory factory = (CmisServiceFactory) servletContext
- .getAttribute(CmisRepositoryContextListener.SERVICES_FACTORY);
+ CmisServiceFactory factory = CmisRepositoryContextListener.getServiceFactory(servletContext);
if (factory == null) {
throw new CmisRuntimeException("Service factory not available! Configuration problem?");
@@ -146,9 +146,35 @@ public abstract class AbstractService {
}
/**
+ * Checks the CSRF token.
+ */
+ protected void checkCsrfToken(WebServiceContext wsContext, boolean isRepositoryInfoRequest) {
+ HttpServletRequest request = (HttpServletRequest) wsContext.getMessageContext().get(
+ MessageContext.SERVLET_REQUEST);
+ HttpServletResponse response = (HttpServletResponse) wsContext.getMessageContext().get(
+ MessageContext.SERVLET_RESPONSE);
+
+ CsrfManager cm = (CsrfManager) request.getAttribute(CmisWebServicesServlet.CSRF_MANAGER);
+
+ cm.check(request, response, isRepositoryInfoRequest, false);
+ }
+
+ /**
* Returns the {@link CmisService} object.
*/
protected CmisService getService(WebServiceContext wsContext, String repositoryId) {
+ checkCsrfToken(wsContext, false);
+ CmisServiceFactory factory = getServiceFactory(wsContext);
+ CallContext context = createContext(wsContext, factory, repositoryId);
+ return factory.getService(context);
+ }
+
+ /**
+ * Returns the {@link CmisService} object for getRepositories() and
+ * getRepositoryInfo() calls.
+ */
+ protected CmisService getServiceForRepositoryInfo(WebServiceContext wsContext, String repositoryId) {
+ checkCsrfToken(wsContext, true);
CmisServiceFactory factory = getServiceFactory(wsContext);
CallContext context = createContext(wsContext, factory, repositoryId);
return factory.getService(context);
Modified: chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings/src/main/java/org/apache/chemistry/opencmis/server/impl/webservices/CmisWebServicesServlet.java
URL: http://svn.apache.org/viewvc/chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings/src/main/java/org/apache/chemistry/opencmis/server/impl/webservices/CmisWebServicesServlet.java?rev=1695555&r1=1695554&r2=1695555&view=diff
==============================================================================
--- chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings/src/main/java/org/apache/chemistry/opencmis/server/impl/webservices/CmisWebServicesServlet.java (original)
+++ chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings/src/main/java/org/apache/chemistry/opencmis/server/impl/webservices/CmisWebServicesServlet.java Wed Aug 12 15:15:57 2015
@@ -39,6 +39,7 @@ import org.apache.chemistry.opencmis.com
import org.apache.chemistry.opencmis.commons.impl.UrlBuilder;
import org.apache.chemistry.opencmis.commons.server.CmisServiceFactory;
import org.apache.chemistry.opencmis.server.impl.CmisRepositoryContextListener;
+import org.apache.chemistry.opencmis.server.shared.CsrfManager;
import org.apache.chemistry.opencmis.server.shared.Dispatcher;
import org.apache.commons.lang.StringEscapeUtils;
import org.apache.cxf.Bus;
@@ -51,6 +52,7 @@ public class CmisWebServicesServlet exte
public static final String PARAM_CMIS_VERSION = "cmisVersion";
public static final String CMIS_VERSION = "org.apache.chemistry.opencmis.cmisVersion";
+ public static final String CSRF_MANAGER = "org.apache.chemistry.opencmis.csrfManager";
private static final long serialVersionUID = 1L;
@@ -69,6 +71,8 @@ public class CmisWebServicesServlet exte
private Map<String, String> docs;
+ private CsrfManager csrfManager;
+
@Override
public void init(ServletConfig config) throws ServletException {
@@ -95,6 +99,9 @@ public class CmisWebServicesServlet exte
docs.put("core", readFile(config, path + "CMIS-Core.xsd.template"));
docs.put("msg", readFile(config, path + "CMIS-Messaging.xsd.template"));
+ // set up CSRF manager
+ csrfManager = new CsrfManager(config);
+
super.init(config);
}
@@ -115,8 +122,9 @@ public class CmisWebServicesServlet exte
@Override
public void handleRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException {
- // set CMIS version
+ // set CMIS version and CSRF Manager
request.setAttribute(CMIS_VERSION, cmisVersion);
+ request.setAttribute(CSRF_MANAGER, csrfManager);
try {
// handle GET requests
@@ -248,8 +256,7 @@ public class CmisWebServicesServlet exte
public void loadBus(ServletConfig servletConfig) {
super.loadBus(servletConfig);
- CmisServiceFactory factory = (CmisServiceFactory) getServletContext().getAttribute(
- CmisRepositoryContextListener.SERVICES_FACTORY);
+ CmisServiceFactory factory = CmisRepositoryContextListener.getServiceFactory(servletConfig.getServletContext());
if (factory == null) {
throw new CmisRuntimeException("Service factory not available! Configuration problem?");
Modified: chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings/src/main/java/org/apache/chemistry/opencmis/server/impl/webservices/RepositoryService.java
URL: http://svn.apache.org/viewvc/chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings/src/main/java/org/apache/chemistry/opencmis/server/impl/webservices/RepositoryService.java?rev=1695555&r1=1695554&r2=1695555&view=diff
==============================================================================
--- chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings/src/main/java/org/apache/chemistry/opencmis/server/impl/webservices/RepositoryService.java (original)
+++ chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings/src/main/java/org/apache/chemistry/opencmis/server/impl/webservices/RepositoryService.java Wed Aug 12 15:15:57 2015
@@ -61,7 +61,7 @@ public class RepositoryService extends A
public List<CmisRepositoryEntryType> getRepositories(CmisExtensionType extension) throws CmisException {
CmisService service = null;
try {
- service = getService(wsContext, null);
+ service = getServiceForRepositoryInfo(wsContext, null);
if (stopBeforeService(service)) {
return null;
@@ -99,7 +99,7 @@ public class RepositoryService extends A
CmisService service = null;
CmisVersion cmisVersion = null;
try {
- service = getService(wsContext, repositoryId);
+ service = getServiceForRepositoryInfo(wsContext, repositoryId);
cmisVersion = getCmisVersion(wsContext);
if (stopBeforeService(service)) {
Modified: chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings/src/main/java/org/apache/chemistry/opencmis/server/shared/AbstractCmisHttpServlet.java
URL: http://svn.apache.org/viewvc/chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings/src/main/java/org/apache/chemistry/opencmis/server/shared/AbstractCmisHttpServlet.java?rev=1695555&r1=1695554&r2=1695555&view=diff
==============================================================================
--- chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings/src/main/java/org/apache/chemistry/opencmis/server/shared/AbstractCmisHttpServlet.java (original)
+++ chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings/src/main/java/org/apache/chemistry/opencmis/server/shared/AbstractCmisHttpServlet.java Wed Aug 12 15:15:57 2015
@@ -28,6 +28,7 @@ import javax.servlet.http.HttpServletReq
import javax.servlet.http.HttpServletResponse;
import org.apache.chemistry.opencmis.commons.enums.CmisVersion;
+import org.apache.chemistry.opencmis.commons.exceptions.CmisPermissionDeniedException;
import org.apache.chemistry.opencmis.commons.impl.ClassLoaderUtil;
import org.apache.chemistry.opencmis.commons.impl.Constants;
import org.apache.chemistry.opencmis.commons.server.CallContext;
@@ -47,6 +48,7 @@ public abstract class AbstractCmisHttpSe
private String binding;
private CmisVersion cmisVersion;
private CallContextHandler callContextHandler;
+ private CsrfManager csrfManager;
@Override
public void init(ServletConfig config) throws ServletException {
@@ -65,12 +67,14 @@ public abstract class AbstractCmisHttpSe
}
// get service factory
- factory = (CmisServiceFactory) config.getServletContext().getAttribute(
- CmisRepositoryContextListener.SERVICES_FACTORY);
+ factory = CmisRepositoryContextListener.getServiceFactory(config.getServletContext());
if (factory == null) {
throw new ServletException("Service factory not available! Configuration problem?");
}
+
+ // set up CSRF manager
+ csrfManager = new CsrfManager(config);
}
/**
@@ -106,6 +110,15 @@ public abstract class AbstractCmisHttpSe
}
/**
+ * Checks the CSRF if configured. Throws an
+ * {@link CmisPermissionDeniedException} if something is wrong.
+ */
+ protected void checkCsrfToken(HttpServletRequest req, HttpServletResponse resp, boolean isRepositoryInfoRequest,
+ boolean isContentRequest) {
+ csrfManager.check(req, resp, isRepositoryInfoRequest, isContentRequest);
+ }
+
+ /**
* Creates a {@link CallContext} object from a servlet request.
*/
protected CallContext createContext(ServletContext servletContext, HttpServletRequest request,
Added: chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings/src/main/java/org/apache/chemistry/opencmis/server/shared/CsrfManager.java
URL: http://svn.apache.org/viewvc/chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings/src/main/java/org/apache/chemistry/opencmis/server/shared/CsrfManager.java?rev=1695555&view=auto
==============================================================================
--- chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings/src/main/java/org/apache/chemistry/opencmis/server/shared/CsrfManager.java (added)
+++ chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings/src/main/java/org/apache/chemistry/opencmis/server/shared/CsrfManager.java Wed Aug 12 15:15:57 2015
@@ -0,0 +1,141 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.chemistry.opencmis.server.shared;
+
+import java.security.SecureRandom;
+
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.HttpSession;
+
+import org.apache.chemistry.opencmis.commons.exceptions.CmisPermissionDeniedException;
+
+public class CsrfManager {
+
+ public static final String CSRF_ATTR = "org.apache.chemistry.opencmis.csrftoken";
+
+ private static final String CSRF_HEADER = "header";
+ private static final String CSRF_PARAMETER = "parameter";
+ private static final String FETCH_VALUE = "fetch";
+
+ private static char[][] hexArrays = new char[][] { "0123456789ABCDEF".toCharArray(), //
+ "0123456789abcdef".toCharArray(), //
+ "ABCDEFGHIJKLMNOP".toCharArray(), //
+ "abcdefghijklmnop".toCharArray() };
+
+ private String csrfHeader;
+ private String csrfParameter;
+
+ private SecureRandom random = new SecureRandom();
+
+ public CsrfManager(String csrfHeader, String csrfParameter) {
+ if (csrfHeader != null) {
+ this.csrfHeader = csrfHeader.trim();
+ if (this.csrfHeader.length() == 0) {
+ throw new IllegalArgumentException("Invalid CSRF header!");
+ }
+ if (csrfParameter != null) {
+ this.csrfParameter = csrfParameter.trim();
+ if (this.csrfParameter.length() == 0) {
+ throw new IllegalArgumentException("Invalid CSRF parameter!");
+ }
+ }
+ }
+ }
+
+ public CsrfManager(ServletConfig config) throws ServletException {
+ csrfHeader = config.getInitParameter(CSRF_HEADER);
+ if (csrfHeader != null) {
+ this.csrfHeader = csrfHeader.trim();
+ if (this.csrfHeader.length() == 0) {
+ throw new ServletException("Invalid CSRF header!");
+ }
+
+ // get parameter
+ csrfParameter = config.getInitParameter(CSRF_PARAMETER);
+ if (csrfParameter != null) {
+ this.csrfParameter = csrfParameter.trim();
+ if (this.csrfParameter.length() == 0) {
+ throw new ServletException("Invalid CSRF parameter!");
+ }
+ }
+ }
+ }
+
+ public void check(HttpServletRequest req, HttpServletResponse resp, boolean isRepositoryInfoRequest,
+ boolean isContentRequest) {
+ if (csrfHeader == null) {
+ // no CSRF protection
+ return;
+ }
+
+ HttpSession httpSession = req.getSession(true);
+ String token = (String) httpSession.getAttribute(CSRF_ATTR);
+ String headerValue = req.getHeader(csrfHeader);
+
+ // check parameter if the header is not set and this is a content
+ // request
+ if (headerValue == null || headerValue.isEmpty()) {
+ if (isContentRequest && csrfParameter != null) {
+ String paramValue = req.getParameter(csrfParameter);
+ if (paramValue != null && paramValue.equals(token)) {
+ return;
+ }
+ }
+
+ throw new CmisPermissionDeniedException("Invalid CSRF token!");
+ }
+
+ // check if a new token is requested
+ if (isRepositoryInfoRequest && FETCH_VALUE.equals(headerValue) && token == null) {
+ token = generateNewToken();
+ httpSession.setAttribute(CSRF_ATTR, token);
+ resp.addHeader(csrfHeader, token);
+ return;
+ }
+
+ // check if there is a token
+ if (token == null) {
+ throw new CmisPermissionDeniedException("Invalid CSRF token!");
+ }
+
+ // finally, check the token
+ if (!token.equals(headerValue)) {
+ throw new CmisPermissionDeniedException("Invalid CSRF token!");
+ }
+ }
+
+ private String generateNewToken() {
+ byte[] tokenBytes = new byte[16];
+ random.nextBytes(tokenBytes);
+
+ int ary = random.nextInt(hexArrays.length);
+
+ char[] token = new char[tokenBytes.length * 2];
+ for (int i = 0; i < tokenBytes.length; i++) {
+ int v = tokenBytes[i] & 0xFF;
+ token[i * 2] = hexArrays[ary][v >>> 4];
+ token[i * 2 + 1] = hexArrays[ary][v & 0x0F];
+ }
+
+ return new String(token);
+ }
+}