diff --git a/src/main/java/org/olat/core/helpers/Settings.java b/src/main/java/org/olat/core/helpers/Settings.java index ebef2b90dfa7a461f7fd3765e4bdbc49263f0028..17d8513e398935855f734a7aab8ea710a5f187bc 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 0000000000000000000000000000000000000000..acdec93b4a59ff2dca6fa3eb91ebb123c78c5e88 --- /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 c2bc567f1156f7b251cecb19338d7a3ddad74666..b88a076c4bf22164b22251bca04463a4b98236ac 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 9ddb18f9f089dcff028fc4937cc76fd98ec8307c..63d1736ed974a890391cec4b9325580acdc21ce3 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 28e771dc555282eea67d415461de3b978785ba64..ea5c9f695a44276a7a7f320a9596e9d860b61d7e 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 d19be54471ab29eebe2c55ecd881b568a45279d9..768669de4ff0e170aa17bebec2fc801a721010e2 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 3aa223e1cf2637fb83525b5bd7e3bc6acbaf1e68..9f04e675c9bec71033c6f4e514379bea0fa0d019 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 -->