cors不适合我的春季启动应用程序

时间:2016-09-22 17:43:47

标签: spring spring-mvc spring-boot cors spring-mvc-test

这是我的webConfig

@Configuration
@EnableWebMvc
public class WebConfig extends WebMvcConfigurerAdapter {

    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**");
    }
}

我有一个/health端点,它会返回一些健康数据并且工作正常。

这是junit test

@Test
    public void corsTest() {
        HttpHeaders headers = new HttpHeaders();
        headers.add(HttpHeaders.ORIGIN, "http://localhost:9000");
        HttpEntity<?> requestEntity = new HttpEntity(headers);
        ResponseEntity<Status> entity = this.restTemplate.exchange("/health", HttpMethod.GET, requestEntity, Status.class);
        assertEquals(HttpStatus.OK, entity.getStatusCode());
        assertEquals("http://localhost:9000", entity.getHeaders().getAccessControlAllowOrigin()); //6
        Status health = entity.getBody();
        assertThat(health.getAppName()).isEqualTo(appName);
    }

测试在第6行失败。如果注释掉该行,则测试通过。 通过调试器,我发现entity.getHeaders().getAccessControlAllowOrigin()为空。我使用这个sample app作为参考,它工作正常。但对于我的申请,它失败了。

当我使用javascript调用/ health api时,我可以看到cors工作。如果我注释掉webConfig类,我会在javascript中收到错误。在javascript上调试更多信息表明,未设置cors响应标头,但在启用webconfig时请求成功提供。

所以绝对是可靠的。这是失败的考验。所以我猜测试是因为我不知道的原因而没有看到它。

3 个答案:

答案 0 :(得分:12)

我认为您需要添加cors origin过滤器,我不确定,但我认为以下解决方案适合您。

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.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;

@Component
@Order(Ordered.HIGHEST_PRECEDENCE)
public class SimpleCORSFilter implements Filter {

    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {

        HttpServletResponse response = (HttpServletResponse) res;
        HttpServletRequest request = (HttpServletRequest) req;
        response.setHeader("Access-Control-Allow-Origin", "*");
        response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE");
        response.setHeader("Access-Control-Max-Age", "3600");
        response.setHeader("Access-Control-Allow-Credentials", "true");
        response.setHeader("Access-Control-Allow-Headers", "Origin,Accept,X-Requested-With,Content-Type,Access-Control-Request-Method,Access-Control-Request-Headers,Authorization");
        if(request.getMethod().equals(HttpMethod.OPTIONS.name())){
            response.setStatus(HttpStatus.NO_CONTENT.value());
        }else{
            chain.doFilter(req, res);
        }
    }

    public void init(FilterConfig filterConfig) {}

    public void destroy() {}
}

答案 1 :(得分:3)

正如我解释here,需要在弹出启动之前将 errorPageFilter 之前的corsfilter设置为加载。否则将破坏CORS支持并且不会引入所需的标题。这可以通过上面指出的@Order(Ordered.HIGHEST_PRECEDENCE)来完成。

答案 2 :(得分:0)

我假设您没有使用注释驱动的cors配置,而是使用java配置。

在这种情况下,我发现你发布的例子和github的例子有区别。

后者使用

registry.addMapping("/greeting-javaconfig").allowedOrigins("http://localhost:9000");

而你的例子错过了allowedOrigins

registry.addMapping("/greeting-javaconfig");

我认为这在这里有所不同。