使用 CORS 的 OPTIONS 请求宁静的跨域
Posted
技术标签:
【中文标题】使用 CORS 的 OPTIONS 请求宁静的跨域【英文标题】:OPTIONS request for restful cross-domain using CORS 【发布时间】:2011-12-26 00:20:16 【问题描述】:在客户端,我将 Ajax.post (jquery 1.5) 与 json 一起使用。在服务器端,我使用的是 resteasy-jaxrs-2.0.1.GA。我发现某处我应该在服务器响应中添加几个标头,并且我已经完成了以下过滤器:
public void doFilter( ServletRequest req,
ServletResponse res,
FilterChain filterChain)
throws IOException, ServletException
MyServletRequestWrapper httpReq = new MyServletRequestWrapper((HttpServletRequest)req);
HttpServletResponse httpRes = (HttpServletResponse)res;
HttpSession session = httpReq.getSession();
httpRes.addHeader(ACCESS_CONTROL_ALLOW_ORIGIN, "*");
httpRes.addHeader(ACCESS_CONTROL_ALLOW_CREDENTIALS, "true");
if (((HttpServletRequest) req).getMethod().equals("OPTIONS"))
httpRes.addHeader(ACCESS_CONTROL_ALLOW_METHODS, "GET, POST, OPTIONS, PUT, DELETE");
httpRes.addHeader(ACCESS_CONTROL_ALLOW_HEADERS, "content-type, x-requested-with, x-requested-by");
filterChain.doFilter(httpReq, httpRes);
它工作正常,因为上面的每个 GET 响应都添加了标头。当我想使用 POST 请求时出现问题。当我使用 Ajax.post 时,首先服务器收到 OPTIONS 请求,并且出现以下错误:
Failed executing OPTIONS [REST_PATH]
org.jboss.resteasy.spi.DefaultOptionsMethodException: No resource method found for options, return OK with Allow header
为了解决上述错误,我尝试使用与 POST ([REST_PATH]) 相同的路径但使用 @OPTION 注释添加方法调用。在那种情况下,javac 告诉我找不到符号 :class OPTIONS,即使附加的 jaxrs 库中有一个 OPTION.class。
有什么解决办法吗?如果有任何线索,我将不胜感激。
【问题讨论】:
【参考方案1】:当我尝试使用 Angular 2 客户端调用我的服务时,RestEasy 以 HTTP 状态 500 和以下错误响应预检请求。
RESTEASY003655:找不到选项的资源方法,返回 OK 允许标题
我尝试了RestEasy's CorsFilter,但我想提出一个简单的替代方案。如果您不想为每个端点编写处理 OPTIONS 调用的代码怎么办?
我实现了一个简单的过滤器:
-
将所需的 CORS 标头应用于响应。
使用 OPTIONS 方法调用端点时返回 HTTP 状态代码 200。您告诉客户其 CORS 预检请求已被接受。
这里是代码。如果您只想在查询“真实”端点时发回 200,请随意优化过滤器。
@Provider
public class CorsFilter implements ContainerResponseFilter
@Override
public void filter(ContainerRequestContext requestContext, ContainerResponseContext responseContext) throws IOException
MultivaluedMap<String, Object> headers = responseContext.getHeaders();
headers.add("Access-Control-Allow-Origin", "*"); // If you want to be more restrictive it could be localhost:4200
headers.add("Access-Control-Allow-Methods", "GET, PUT, POST, OPTIONS"); // You can add HEAD, DELETE, TRACE, PATCH
headers.add("Access-Control-Allow-Headers", "Content-Type, Authorization, Accept, Accept-Language"); // You can add many more
if (requestContext.getMethod().equals("OPTIONS"))
responseContext.setStatus(200);
确保也understand CORS。
【讨论】:
【参考方案2】:tomcat 中有一个内置的 CORS 过滤器。 http://tomcat.apache.org/tomcat-7.0-doc/config/filter.html
<filter>
<filter-name>CorsFilter</filter-name>
<filter-class>org.apache.catalina.filters.CorsFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>CorsFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
【讨论】:
【参考方案3】:CORS 过滤器可能没问题。我想指出你写的“为了解决上述错误,我试图添加与 POST ([REST_PATH]) 相同的路径但带有 @OPTION 注释的方法调用。在这种情况下,javac 告诉我符号 :class OPTIONS 可以找不到,“你在那里写了一个错字而不是@OPTION<strong>S</strong>
你写了@OPTION
没有<strong>S</strong>
:)
【讨论】:
【参考方案4】:这个问题已经很老了,但作为其他有类似问题的人的参考 - 最近我遇到了一个不错的“CORS 过滤器”,您可能想考虑使用。只需将以下几行添加到您的 web.xml 中,它就像一个魅力。
<filter>
<filter-name>CORS</filter-name>
<filter-class>com.thetransactioncompany.cors.CORSFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>CORS</filter-name>
<servlet-name>MyServletNameGoesHere</servlet-name>
</filter-mapping>
和maven依赖:
<dependency>
<groupId>com.thetransactioncompany</groupId>
<artifactId>cors-filter</artifactId>
<version>1.5.1</version>
</dependency>
【讨论】:
以上是关于使用 CORS 的 OPTIONS 请求宁静的跨域的主要内容,如果未能解决你的问题,请参考以下文章