Skip to content

Commit

Permalink
ENG-128 added support for configuring cors headers from systemParams (#…
Browse files Browse the repository at this point in the history
…897)

* ENG-128 added support for configuring cors headers from systemParams.properties

* ENG-128 cleaning up

* ENG-128 added fallback systemParams properties to environment variables

* ENG-128 converted CORSFilter into spring bean to enable configuration from pom instead of systemParams

* ENG-128 adding enabled property to CORS Filter

* ENG-128 fixing tests

* ENG-128 fixing tests

* ENG-128 fixing tests

Co-authored-by: Filipe Leandro <ffleandro>
  • Loading branch information
ffleandro authored May 20, 2020
1 parent c7c3705 commit ece657d
Show file tree
Hide file tree
Showing 14 changed files with 129 additions and 43 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -14,38 +14,83 @@
package org.entando.entando.aps.servlet.security;

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.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.filter.OncePerRequestFilter;

/**
*
* @author paddeo
* @author paddeo, f.leandro
*/
public class CORSFilter extends OncePerRequestFilter {
public class CORSFilter implements Filter {

private final Logger logger = LoggerFactory.getLogger(getClass());

public static final String ALLOWED_METHODS = "GET, POST, PUT, DELETE, OPTIONS, PATCH";

private boolean enabled;
private String allowedOrigins;
private String allowedMethods;
private String allowedHeaders;
private String allowedCredentials;
private String maxAge;

@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
logger.trace("Sending Header....");
public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain)
throws IOException, ServletException {
final HttpServletRequest httpRequest = (HttpServletRequest) request;
final HttpServletResponse httpResponse = (HttpServletResponse) response;

if (!enabled) {
filterChain.doFilter(httpRequest, httpResponse);
return;
}

logger.trace("Configuring CORS Headers....");
// CORS "pre-flight" request
response.addHeader("Access-Control-Allow-Origin", "*");
response.addHeader("Access-Control-Allow-Methods", ALLOWED_METHODS);
response.addHeader("Access-Control-Allow-Headers", "Content-Type, Authorization");
response.addHeader("Access-Control-Max-Age", "3600");

if ("OPTIONS".equalsIgnoreCase(request.getMethod())) {
response.setStatus(HttpServletResponse.SC_OK);
httpResponse.addHeader("Access-Control-Allow-Origin", allowedOrigins);
httpResponse.addHeader("Access-Control-Allow-Methods", allowedMethods);
httpResponse.addHeader("Access-Control-Allow-Headers", allowedHeaders);
httpResponse.addHeader("Access-Control-Allow-Credentials", allowedCredentials);
httpResponse.addHeader("Access-Control-Max-Age", maxAge);

if ("OPTIONS".equalsIgnoreCase(httpRequest.getMethod())) {
httpResponse.setStatus(HttpServletResponse.SC_OK);
} else {
filterChain.doFilter(request, response);
filterChain.doFilter(httpRequest, httpResponse);
}
}

@Override public void init(final FilterConfig filterConfig) {}
@Override public void destroy() {}

public void setAllowedOrigins(String allowedOrigins) {
this.allowedOrigins = allowedOrigins;
}

public void setAllowedMethods(String allowedMethods) {
this.allowedMethods = allowedMethods;
}

public void setAllowedHeaders(String allowedHeaders) {
this.allowedHeaders = allowedHeaders;
}

public void setAllowedCredentials(String allowedCredentials) {
this.allowedCredentials = allowedCredentials;
}

public void setMaxAge(String maxAge) {
this.maxAge = maxAge;
}

public void setEnabled(boolean enabled) {
this.enabled = enabled;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
*/
package org.entando.entando.aps.servlet.security;

import javax.servlet.ServletContext;
import org.springframework.security.web.context.AbstractSecurityWebApplicationInitializer;

/**
Expand All @@ -23,10 +22,4 @@
*/
public class SecurityWebApplicationInitializer extends AbstractSecurityWebApplicationInitializer {

@Override
protected void beforeSpringSecurityFilterChain(ServletContext servletContext) {
super.beforeSpringSecurityFilterChain(servletContext);
super.insertFilters(servletContext, new CORSFilter());
}

}
16 changes: 16 additions & 0 deletions engine/src/main/resources/spring/aps/cors.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

<bean id="corsFilter"
class="org.entando.entando.aps.servlet.security.CORSFilter">
<property name="enabled" value="${cors.enabled:true}" />
<property name="allowedOrigins" value="${cors.access.control.allow.origin:*}" />
<property name="allowedHeaders" value="${cors.access.control.allow.headers:Content-Type, Authorization}" />
<property name="allowedMethods" value="${cors.access.control.allow.methods:GET, POST, PUT, DELETE, OPTIONS, PATCH}" />
<property name="allowedCredentials" value="${cors.access.control.allow.credentials:false}" />
<property name="maxAge" value="${cors.access.control.maxAge:3600}" />
</bean>

</beans>
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,12 @@
*/
package org.entando.entando.web;

import javax.annotation.Resource;

import com.agiletec.aps.system.SystemConstants;
import com.agiletec.aps.system.services.authorization.IAuthorizationManager;
import com.agiletec.aps.system.services.baseconfig.ConfigInterface;
import com.agiletec.aps.system.services.user.IAuthenticationProviderManager;
import com.agiletec.aps.system.services.user.UserDetails;
import javax.annotation.Resource;
import javax.servlet.Filter;
import org.entando.entando.TestEntandoJndiUtils;
import org.entando.entando.aps.servlet.security.CORSFilter;
Expand All @@ -31,6 +32,7 @@
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;
Expand Down Expand Up @@ -80,8 +82,17 @@ public static void setup() throws Exception {
@Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);

CORSFilter filter = new CORSFilter();
filter.setEnabled(true);
filter.setAllowedOrigins("*");
filter.setAllowedMethods("GET, POST, PUT, DELETE, OPTIONS, PATCH");
filter.setAllowedHeaders("Content-Type, Authorization");
filter.setAllowedCredentials("false");
filter.setMaxAge("3600");

mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext)
.addFilters(new CORSFilter(), springSecurityFilterChain)
.addFilters(filter, springSecurityFilterChain)
.build();
accessToken = null;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,8 +70,9 @@ public void testGetCategories() throws Exception {
.header("Authorization", "Bearer " + accessToken));
result.andExpect(status().isOk());
result.andExpect(header().string("Access-Control-Allow-Origin", "*"));
result.andExpect(header().string("Access-Control-Allow-Methods", CORSFilter.ALLOWED_METHODS));
result.andExpect(header().string("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS, PATCH"));
result.andExpect(header().string("Access-Control-Allow-Headers", "Content-Type, Authorization"));
result.andExpect(header().string("Access-Control-Allow-Credentials", "false"));
result.andExpect(header().string("Access-Control-Max-Age", "3600"));
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
import org.junit.Test;
import org.mockito.InjectMocks;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.MediaType;
import org.springframework.test.web.servlet.ResultActions;
import org.springframework.test.web.servlet.ResultMatcher;
Expand Down Expand Up @@ -64,8 +65,9 @@ public void testGetDataTypes() throws Exception {
.header("Authorization", "Bearer " + accessToken));
result.andExpect(status().isOk());
result.andExpect(header().string("Access-Control-Allow-Origin", "*"));
result.andExpect(header().string("Access-Control-Allow-Methods", CORSFilter.ALLOWED_METHODS));
result.andExpect(header().string("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS, PATCH"));
result.andExpect(header().string("Access-Control-Allow-Headers", "Content-Type, Authorization"));
result.andExpect(header().string("Access-Control-Allow-Credentials", "false"));
result.andExpect(header().string("Access-Control-Max-Age", "3600"));
}

Expand Down Expand Up @@ -250,8 +252,9 @@ public void testGetDataTypeAttributeTypes_1() throws Exception {
.header("Authorization", "Bearer " + accessToken));
result.andExpect(status().isOk());
result.andExpect(header().string("Access-Control-Allow-Origin", "*"));
result.andExpect(header().string("Access-Control-Allow-Methods", CORSFilter.ALLOWED_METHODS));
result.andExpect(header().string("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS, PATCH"));
result.andExpect(header().string("Access-Control-Allow-Headers", "Content-Type, Authorization"));
result.andExpect(header().string("Access-Control-Allow-Credentials", "false"));
result.andExpect(header().string("Access-Control-Max-Age", "3600"));
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,9 @@ public void testCheckRequest() throws Exception {
.header("Authorization", "Bearer " + accessToken));
result.andExpect(status().isOk());
result.andExpect(header().string("Access-Control-Allow-Origin", "*"));
result.andExpect(header().string("Access-Control-Allow-Methods", CORSFilter.ALLOWED_METHODS));
result.andExpect(header().string("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS, PATCH"));
result.andExpect(header().string("Access-Control-Allow-Headers", "Content-Type, Authorization"));
result.andExpect(header().string("Access-Control-Allow-Credentials", "false"));
result.andExpect(header().string("Access-Control-Max-Age", "3600"));
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,9 @@ public void testGetFragments_1() throws Exception {
result.andDo(print());
result.andExpect(status().isOk());
result.andExpect(header().string("Access-Control-Allow-Origin", "*"));
result.andExpect(header().string("Access-Control-Allow-Methods", CORSFilter.ALLOWED_METHODS));
result.andExpect(header().string("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS, PATCH"));
result.andExpect(header().string("Access-Control-Allow-Headers", "Content-Type, Authorization"));
result.andExpect(header().string("Access-Control-Allow-Credentials", "false"));
result.andExpect(header().string("Access-Control-Max-Age", "3600"));
result.andExpect(jsonPath("$.payload", Matchers.hasSize(1)));
result.andExpect(jsonPath("$.errors", Matchers.hasSize(0)));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,8 +65,9 @@ public void testGetLangs() throws Exception {
* org.entando.entando.aps.servlet.CORSFilter class
*/
result.andExpect(header().string("Access-Control-Allow-Origin", "*"));
result.andExpect(header().string("Access-Control-Allow-Methods", CORSFilter.ALLOWED_METHODS));
result.andExpect(header().string("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS, PATCH"));
result.andExpect(header().string("Access-Control-Allow-Headers", "Content-Type, Authorization"));
result.andExpect(header().string("Access-Control-Allow-Credentials", "false"));
result.andExpect(header().string("Access-Control-Max-Age", "3600"));
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,9 @@ public void should_execute_reload_and_have_headers() throws Exception {
* org.entando.entando.aps.servlet.CORSFilter class
*/
result.andExpect(header().string("Access-Control-Allow-Origin", "*"));
result.andExpect(header().string("Access-Control-Allow-Methods", CORSFilter.ALLOWED_METHODS));
result.andExpect(header().string("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS, PATCH"));
result.andExpect(header().string("Access-Control-Allow-Headers", "Content-Type, Authorization"));
result.andExpect(header().string("Access-Control-Allow-Credentials", "false"));
result.andExpect(header().string("Access-Control-Max-Age", "3600"));
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,13 @@
*/
package org.entando.entando.web.user;

import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertThat;
import static org.mockito.Mockito.when;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;

import com.agiletec.aps.system.exception.ApsSystemException;
import com.agiletec.aps.system.services.authorization.IAuthorizationManager;
import com.agiletec.aps.system.services.user.IAuthenticationProviderManager;
Expand Down Expand Up @@ -43,13 +50,6 @@
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.context.WebApplicationContext;

import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertThat;
import static org.mockito.Mockito.when;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {
"classpath*:spring/testpropertyPlaceholder.xml",
Expand Down Expand Up @@ -90,8 +90,17 @@ public static void setup() throws Exception {
@Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);

CORSFilter filter = new CORSFilter();
filter.setEnabled(true);
filter.setAllowedOrigins("*");
filter.setAllowedMethods("GET, POST, PUT, DELETE, OPTIONS, PATCH");
filter.setAllowedHeaders("Content-Type, Authorization");
filter.setAllowedCredentials("false");
filter.setMaxAge("3600");

mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext)
.addFilters(new CORSFilter())
.addFilters(filter)
.build();

//workaround for dirty context
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,9 @@ public void testGetUserProfileTypes() throws Exception {
.header("Authorization", "Bearer " + accessToken));
result.andExpect(status().isOk());
result.andExpect(header().string("Access-Control-Allow-Origin", "*"));
result.andExpect(header().string("Access-Control-Allow-Methods", CORSFilter.ALLOWED_METHODS));
result.andExpect(header().string("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS, PATCH"));
result.andExpect(header().string("Access-Control-Allow-Headers", "Content-Type, Authorization"));
result.andExpect(header().string("Access-Control-Allow-Credentials", "false"));
result.andExpect(header().string("Access-Control-Max-Age", "3600"));
}

Expand Down Expand Up @@ -253,8 +254,9 @@ public void testGetUserProfileAttributeTypes_1() throws Exception {
.header("Authorization", "Bearer " + accessToken));
result.andExpect(status().isOk());
result.andExpect(header().string("Access-Control-Allow-Origin", "*"));
result.andExpect(header().string("Access-Control-Allow-Methods", CORSFilter.ALLOWED_METHODS));
result.andExpect(header().string("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS, PATCH"));
result.andExpect(header().string("Access-Control-Allow-Headers", "Content-Type, Authorization"));
result.andExpect(header().string("Access-Control-Allow-Credentials", "false"));
result.andExpect(header().string("Access-Control-Max-Age", "3600"));
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,8 +69,9 @@ public void testGetUserProfileType() throws Exception {
System.out.println(result.andReturn().getResponse().getContentAsString());
result.andExpect(status().isOk());
result.andExpect(header().string("Access-Control-Allow-Origin", "*"));
result.andExpect(header().string("Access-Control-Allow-Methods", CORSFilter.ALLOWED_METHODS));
result.andExpect(header().string("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS, PATCH"));
result.andExpect(header().string("Access-Control-Allow-Headers", "Content-Type, Authorization"));
result.andExpect(header().string("Access-Control-Allow-Credentials", "false"));
result.andExpect(header().string("Access-Control-Max-Age", "3600"));
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,9 @@ public void testGetCategories() throws Exception {
.header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken));
result.andExpect(status().isOk());
result.andExpect(header().string("Access-Control-Allow-Origin", "*"));
result.andExpect(header().string("Access-Control-Allow-Methods", CORSFilter.ALLOWED_METHODS));
result.andExpect(header().string("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS, PATCH"));
result.andExpect(header().string("Access-Control-Allow-Headers", "Content-Type, Authorization"));
result.andExpect(header().string("Access-Control-Allow-Credentials", "false"));
result.andExpect(header().string("Access-Control-Max-Age", "3600"));
}

Expand Down

0 comments on commit ece657d

Please sign in to comment.