diff --git a/src/main/java/li/strolch/rest/DefaultStrolchSessionHandler.java b/src/main/java/li/strolch/rest/DefaultStrolchSessionHandler.java index 93c33e824..a28fcd1b6 100644 --- a/src/main/java/li/strolch/rest/DefaultStrolchSessionHandler.java +++ b/src/main/java/li/strolch/rest/DefaultStrolchSessionHandler.java @@ -58,10 +58,12 @@ public class DefaultStrolchSessionHandler extends StrolchComponent implements St @Override public void stop() { - for (Certificate certificate : this.certificateMap.values()) { - this.privilegeHandler.invalidateSession(certificate); + if (this.certificateMap != null) { + for (Certificate certificate : this.certificateMap.values()) { + this.privilegeHandler.invalidateSession(certificate); + } + this.certificateMap.clear(); } - this.certificateMap.clear(); this.privilegeHandler = null; super.stop(); } diff --git a/src/main/java/li/strolch/rest/RestfulStrolchComponent.java b/src/main/java/li/strolch/rest/RestfulStrolchComponent.java index 0c08c1fec..982501667 100644 --- a/src/main/java/li/strolch/rest/RestfulStrolchComponent.java +++ b/src/main/java/li/strolch/rest/RestfulStrolchComponent.java @@ -17,6 +17,8 @@ package li.strolch.rest; import li.strolch.agent.api.ComponentContainer; import li.strolch.agent.api.StrolchComponent; +import li.strolch.rest.filters.AccessControlResponseFilter; +import li.strolch.runtime.configuration.ComponentConfiguration; import ch.eitchnet.utils.dbc.DBC; /** @@ -34,6 +36,18 @@ public class RestfulStrolchComponent extends StrolchComponent { super(container, componentName); } + @Override + public void initialize(ComponentConfiguration configuration) { + + if (configuration.getBoolean("corsEnabled", Boolean.FALSE)) { + AccessControlResponseFilter.setCorsEnabled(true); + String origin = configuration.getString("corsOrigin", null); + AccessControlResponseFilter.setOrigin(origin); + } + + super.initialize(configuration); + } + @Override public void start() { DBC.PRE.assertNull("Instance is already set! This component is a singleton resource!", instance); diff --git a/src/main/java/li/strolch/rest/StrolchRestfulClasses.java b/src/main/java/li/strolch/rest/StrolchRestfulClasses.java index 3540dd3ce..26cf42cb7 100644 --- a/src/main/java/li/strolch/rest/StrolchRestfulClasses.java +++ b/src/main/java/li/strolch/rest/StrolchRestfulClasses.java @@ -23,6 +23,7 @@ import li.strolch.rest.endpoint.AuthenticationService; import li.strolch.rest.endpoint.EnumQuery; import li.strolch.rest.endpoint.Inspector; import li.strolch.rest.endpoint.VersionQuery; +import li.strolch.rest.filters.AccessControlResponseFilter; /** * @author Robert von Burg @@ -41,6 +42,7 @@ public class StrolchRestfulClasses { Set> providerClasses = new HashSet<>(); providerClasses.add(StrolchRestfulExceptionMapper.class); + providerClasses.add(AccessControlResponseFilter.class); StrolchRestfulClasses.restfulClasses = Collections.unmodifiableSet(restfulClasses); StrolchRestfulClasses.providerClasses = Collections.unmodifiableSet(providerClasses); diff --git a/src/main/java/li/strolch/rest/filters/AccessControlResponseFilter.java b/src/main/java/li/strolch/rest/filters/AccessControlResponseFilter.java new file mode 100644 index 000000000..e4c684de7 --- /dev/null +++ b/src/main/java/li/strolch/rest/filters/AccessControlResponseFilter.java @@ -0,0 +1,61 @@ +package li.strolch.rest.filters; + +import java.io.IOException; + +import javax.annotation.Priority; +import javax.ws.rs.Priorities; +import javax.ws.rs.container.ContainerRequestContext; +import javax.ws.rs.container.ContainerResponseContext; +import javax.ws.rs.container.ContainerResponseFilter; +import javax.ws.rs.core.MultivaluedMap; +import javax.ws.rs.ext.Provider; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +@Provider +@Priority(Priorities.HEADER_DECORATOR) +public class AccessControlResponseFilter implements ContainerResponseFilter { + + private static final Logger logger = LoggerFactory.getLogger(AccessControlResponseFilter.class); + + private static boolean corsEnabled; + private static String origin; + private static boolean logged; + + /** + * @param corsEnabled + * the corsEnabled to set + */ + public static void setCorsEnabled(boolean corsEnabled) { + AccessControlResponseFilter.corsEnabled = corsEnabled; + } + + /** + * @param origin + * the origin to set + */ + public static void setOrigin(String origin) { + AccessControlResponseFilter.origin = origin; + } + + @Override + public void filter(ContainerRequestContext requestContext, ContainerResponseContext responseContext) + throws IOException { + + if (!corsEnabled) + return; + + if (!logged) { + logged = true; + logger.info("Enabling CORS for origin: " + origin); + } + + MultivaluedMap headers = responseContext.getHeaders(); + + headers.add("Access-Control-Allow-Origin", origin); + headers.add("Access-Control-Allow-Headers", "Authorization, Origin, X-Requested-With, Content-Type"); + headers.add("Access-Control-Expose-Headers", "Location, Content-Disposition"); + headers.add("Access-Control-Allow-Methods", "POST, PUT, GET, DELETE, HEAD, OPTIONS"); + } +} \ No newline at end of file