From c3cb1c85b95bf26c5bb946e44b249bbc841c9e82 Mon Sep 17 00:00:00 2001 From: srosse <none@none> Date: Mon, 27 May 2013 10:15:02 +0200 Subject: [PATCH] OO-615: implements a simple filter to allow CORS (cross origin resource sharing) but restricted to the rest api --- .../java/org/olat/core/helpers/Settings.java | 9 ++ .../olat/core/servlets/CrossOriginFilter.java | 86 +++++++++++++++++++ .../resources/serviceconfig/brasatoconfig.xml | 1 + .../resources/serviceconfig/olat.properties | 5 ++ src/main/webapp-gae/WEB-INF/web.xml | 10 +++ src/main/webapp-jbossas7/WEB-INF/web.xml | 10 +++ src/main/webapp-tomcat/WEB-INF/web.xml | 11 ++- 7 files changed, 131 insertions(+), 1 deletion(-) create mode 100644 src/main/java/org/olat/core/servlets/CrossOriginFilter.java diff --git a/src/main/java/org/olat/core/helpers/Settings.java b/src/main/java/org/olat/core/helpers/Settings.java index ebef2b90dfa..17d8513e398 100644 --- a/src/main/java/org/olat/core/helpers/Settings.java +++ b/src/main/java/org/olat/core/helpers/Settings.java @@ -86,6 +86,7 @@ public class Settings implements Initializable, Destroyable, GenericEventListene private static Date buildDate; private static String repoRevision; private static String patchRepoRevision; + private static String crossOriginFilter; /** * [used by spring] @@ -447,6 +448,14 @@ public class Settings implements Initializable, Destroyable, GenericEventListene return createServerURI() + WebappHelper.getServletContextPath(); } + public static String getCrossOriginFilter() { + return crossOriginFilter; + } + + public void setCrossOriginFilter(String crossOriginFilter) { + Settings.crossOriginFilter = crossOriginFilter; + } + /** * @return True if this is a JUnit test. * diff --git a/src/main/java/org/olat/core/servlets/CrossOriginFilter.java b/src/main/java/org/olat/core/servlets/CrossOriginFilter.java new file mode 100644 index 00000000000..acdec93b4a5 --- /dev/null +++ b/src/main/java/org/olat/core/servlets/CrossOriginFilter.java @@ -0,0 +1,86 @@ +/** + * <p> + * Copyright (c) frentix GmbH<br> + * http://www.frentix.com<br> + */ +package org.olat.core.servlets; + +import java.io.IOException; + +import javax.servlet.Filter; +import javax.servlet.FilterChain; +import javax.servlet.FilterConfig; +import javax.servlet.ServletException; +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.olat.core.helpers.Settings; +import org.olat.core.util.StringHelper; + +/** + * + * Allow cross origin for our javascript client + * + * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com + */ +public class CrossOriginFilter implements Filter { + + @Override + public void init(FilterConfig filterConfig) throws ServletException { + // + } + + @Override + public void destroy() { + // + } + + @Override + public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { + addHeaders(request, response); + chain.doFilter(request, response); + addHeaders(request, response); + } + + private void addHeaders(ServletRequest request, ServletResponse response) { + if(response instanceof HttpServletResponse) { + HttpServletRequest httpRequest = (HttpServletRequest)request; + HttpServletResponse httpResponse = (HttpServletResponse)response; + String origin = httpRequest.getHeader("origin"); + if(isDomainAllowed(origin)) { + if(origin != null && !origin.isEmpty()) { + httpResponse.setHeader("Access-Control-Allow-Origin", origin); + } + String headers = httpRequest.getHeader("access-control-request-headers"); + if(headers != null && !headers.isEmpty()) { + httpResponse.setHeader("Access-Control-Allow-Headers", headers); + } + httpResponse.setHeader("Access-Control-Allow-Methods", "POST, PUT, DELETE, GET, OPTIONS"); + httpResponse.setHeader("Access-Control-Max-Age", "1728000"); + + String method = httpRequest.getHeader("access-control-request-method"); + if("OPTIONS".equals(method)) { + httpResponse.setHeader("Access-Control-Allow-Credentials", "true"); + } + } + } + } + + private boolean isDomainAllowed(String origin) { + String allowedDomains = Settings.getCrossOriginFilter(); + if(StringHelper.containsNonWhitespace(allowedDomains) && StringHelper.containsNonWhitespace(origin)) { + if("*".equals(allowedDomains)) { + return true; + } + String[] domains = allowedDomains.split(","); + for(String domain:domains) { + if(domain.equals(origin)) { + return true; + } + } + } + return false; + } +} \ No newline at end of file diff --git a/src/main/resources/serviceconfig/brasatoconfig.xml b/src/main/resources/serviceconfig/brasatoconfig.xml index c2bc567f115..b88a076c4bf 100644 --- a/src/main/resources/serviceconfig/brasatoconfig.xml +++ b/src/main/resources/serviceconfig/brasatoconfig.xml @@ -87,6 +87,7 @@ <value>.*Lynx.*</value> <!-- Lynx console browser (no js) --> </list> </property> + <property name="crossOriginFilter" value="${allow.cross.origin.domain}"/> <!-- Set the system theme here. Make sure the directory webapp/WEB-INF/static/themes/YOURTHEME exists. This is only the default value in case no user configuration is found. Use the administration GUI to diff --git a/src/main/resources/serviceconfig/olat.properties b/src/main/resources/serviceconfig/olat.properties index 9ddb18f9f08..63d1736ed97 100644 --- a/src/main/resources/serviceconfig/olat.properties +++ b/src/main/resources/serviceconfig/olat.properties @@ -434,6 +434,11 @@ server.modjk.enabled=false # OLAT JMX server port (must be unique per node in a cluster) jmx.rmi.port=3000 +#allow an other web site to use the REST API with Javascript +#list of domains separated with , or * for allow all +allow.cross.origin.domain= +allow.cross.origin.domain.values=*,www.frentix.com + ######################################################################## # Database settings ######################################################################## diff --git a/src/main/webapp-gae/WEB-INF/web.xml b/src/main/webapp-gae/WEB-INF/web.xml index 28e771dc555..ea5c9f695a4 100644 --- a/src/main/webapp-gae/WEB-INF/web.xml +++ b/src/main/webapp-gae/WEB-INF/web.xml @@ -88,6 +88,11 @@ <filter-class>org.olat.resource.accesscontrol.provider.paypal.PaypalIPNFilter</filter-class> </filter> + <filter> + <filter-name>CrossOriginFilter</filter-name> + <filter-class>org.olat.core.servlets.CrossOriginFilter</filter-class> + </filter> + <filter> <filter-name>RESTApiLoginFilter</filter-name> <filter-class>org.olat.restapi.security.RestApiLoginFilter</filter-class> @@ -110,6 +115,11 @@ <url-pattern>/paypal/*</url-pattern> </filter-mapping> + <filter-mapping> + <filter-name>CrossOriginFilter</filter-name> + <url-pattern>/restapi/*</url-pattern> + </filter-mapping> + <filter-mapping> <filter-name>RESTApiLoginFilter</filter-name> <url-pattern>/restapi/*</url-pattern> diff --git a/src/main/webapp-jbossas7/WEB-INF/web.xml b/src/main/webapp-jbossas7/WEB-INF/web.xml index d19be54471a..768669de4ff 100644 --- a/src/main/webapp-jbossas7/WEB-INF/web.xml +++ b/src/main/webapp-jbossas7/WEB-INF/web.xml @@ -88,6 +88,11 @@ <filter-class>org.olat.resource.accesscontrol.provider.paypal.PaypalIPNFilter</filter-class> </filter> + <filter> + <filter-name>CrossOriginFilter</filter-name> + <filter-class>org.olat.core.servlets.CrossOriginFilter</filter-class> + </filter> + <filter> <filter-name>RESTApiLoginFilter</filter-name> <filter-class>org.olat.restapi.security.RestApiLoginFilter</filter-class> @@ -110,6 +115,11 @@ <url-pattern>/paypal/*</url-pattern> </filter-mapping> + <filter-mapping> + <filter-name>CrossOriginFilter</filter-name> + <url-pattern>/restapi/*</url-pattern> + </filter-mapping> + <filter-mapping> <filter-name>RESTApiLoginFilter</filter-name> <url-pattern>/restapi/*</url-pattern> diff --git a/src/main/webapp-tomcat/WEB-INF/web.xml b/src/main/webapp-tomcat/WEB-INF/web.xml index 3aa223e1cf2..9f04e675c9b 100644 --- a/src/main/webapp-tomcat/WEB-INF/web.xml +++ b/src/main/webapp-tomcat/WEB-INF/web.xml @@ -83,6 +83,11 @@ <filter-class>org.olat.resource.accesscontrol.provider.paypal.PaypalIPNFilter</filter-class> </filter> + <filter> + <filter-name>CrossOriginFilter</filter-name> + <filter-class>org.olat.core.servlets.CrossOriginFilter</filter-class> + </filter> + <filter> <filter-name>RESTApiLoginFilter</filter-name> <filter-class>org.olat.restapi.security.RestApiLoginFilter</filter-class> @@ -94,11 +99,15 @@ <url-pattern>/paypal/*</url-pattern> </filter-mapping> + <filter-mapping> + <filter-name>CrossOriginFilter</filter-name> + <url-pattern>/restapi/*</url-pattern> + </filter-mapping> + <filter-mapping> <filter-name>RESTApiLoginFilter</filter-name> <url-pattern>/restapi/*</url-pattern> </filter-mapping> - <!-- 3. Listeners --> <!-- triggers the above spring files to be processed by the spring framework --> -- GitLab