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 回答的启发,但我无法评论他的回答以添加我的详细信息。
我使用 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 CORSFilterpackage 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 回答的启发,但我无法评论他的回答以添加我的详细信息。