Spring - Resteasy - Cors Double Access-Control-Allow-Origin header 回应

Spring - Resteasy - Cors Double Access-Control-Allow-Origin header in response

我使用 Spring 3 和 Resteasy 设置了一个网络应用程序;因为我的资源需要身份验证,所以我不允许将 * 用作 Access-Control-Allow-Origin。 所以我配置了

org.jboss.resteasy.plugins.interceptors.CorsFilter

具有正确的原始域。 这适用于桌面客户端(Mac Os 等的 Paw),但不适用于浏览器(Chrome);问题是响应包含 Access-Control-Allow-Origin 的双精度值,即我配置的值和 '*'。

CorsFilter 不是罪魁祸首,因为即使您配置了多个来源,它始终只为 header 提供一个值,即请求要求的值。

我根本不知道是谁放了额外的(而且是错误的)header,知道我可以在哪里寻找吗? 请注意,双 header 出现在 GET 请求上,但不会出现在 OPTIONS 请求上。

我不确定你加倍的 header 来自哪里,但你是否尝试过使用自定义过滤器? 例如:

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

public SimpleCorsFilter() {
}

@Override
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, PUT");
        response.setHeader("Access-Control-Max-Age", "3600");
        response.setHeader("Access-Control-Allow-Headers", "X-Requested-With, Authorization, Content-Type");

        if ("OPTIONS".equalsIgnoreCase(request.getMethod())) {
            response.setStatus(HttpServletResponse.SC_OK);
        } else {
            chain.doFilter(req, res);
        }
    }

    @Override
    public void init(FilterConfig filterConfig) {
    }

    @Override
    public void destroy() {
    }

}

我终于发现类路径中有一个专有的 MessageBodyWriterInterceptor 做了一个错误的添加头;现在我要删除它。 我了解到的一件事是,如果只有在有主体可写时才会发生某些事情,那么一个好的起点肯定是渲染管道

我已经尝试了以下操作并且非常有效:

首先,在您的 web.xml:

中注册 CorsFilter 提供程序 class
<context-param>
    <param-name>resteasy.providers</param-name>
    <param-value>org.jboss.resteasy.plugins.interceptors.CorsFilter</param-value>
</context-param>

这样做,您的服务器已经可以处理 CORS 请求,但是,您需要添加一些允许的源以使其正常工作,因此,您应该可以访问 RestEasy 然后创建的 CorsFilter 实例添加您希望授予访问权限的所有 URL,或者如果您希望授予任何访问权限,请添加 *。

在这方面,如果您正在使用 RestEasy Spring 集成,您需要通过将 org.jboss.resteasy.spi.ResteasyProviderFactory class 的实例自动装配到您的代码中来获取它:

@Autowired
private ResteasyProviderFactory processor;

然后使用带有 @PostConstruct 注释的设置方法从 ResteasyProviderFactory 获取 CorsFilter 的实例,如下面的代码片段:

@PostConstruct
public void setUp() {
    ContainerRequestFilter[] requestFilters = processor.getContainerRequestFilterRegistry().preMatch();
    CorsFilter filter = (CorsFilter) Iterables.getLast(Iterables.filter(Arrays.asList(requestFilters), Predicates.instanceOf(CorsFilter.class)));
    filter.getAllowedOrigins().add("*");
}

P.S.: 我正在使用这个框架:

  • Spring 框架 3.2.18.RELEASE
  • RestEasy 3.0.12.Final

希望对您有所帮助!

对于那些像我一样苦苦挣扎但不使用应用程序启动器而只使用 Spring + Reasteasy 的人。

只需添加 web.xml:

<context-param>
    <param-name>resteasy.providers</param-name>
    <param-value>package.to.your.cors.CORSFilter</param-value>
</context-param>

并像

这样创建 Java Class CORSFilter
package package.to.your.cors;

import java.io.IOException;

import javax.ws.rs.container.ContainerRequestContext;
import javax.ws.rs.container.ContainerResponseContext;
import javax.ws.rs.container.ContainerResponseFilter;
import javax.ws.rs.ext.Provider;

@Provider
public class CORSFilter implements ContainerResponseFilter {

    @Override
    public void filter(final ContainerRequestContext requestContext,
                       final ContainerResponseContext cres) throws IOException {
        cres.getHeaders().add("Access-Control-Allow-Origin", "*");
        cres.getHeaders().add("Access-Control-Allow-Methods", "POST, GET, PUT, OPTIONS, DELETE");
        cres.getHeaders().add("Access-Control-Allow-Headers", "X-Auth-Token, Content-Type");
        cres.getHeaders().add("Access-Control-Max-Age", "4800");
    }

}

它就像一个魅力。

PS:受到 s_bighead 回答的启发,但我无法评论他的回答以添加我的详细信息。