首先,通过阅读Mozilla的官方文档,对CORS的解决方案进行了理解。
然后,自己动手做实验来验证一下这个方案。
结果,发现当我在“Access-Control-Allow-Methods”中未设置“POST”时,页面上的POST仍然可以发送成功。无法理解,请各位赐教!
如下是我的请求截图:
按照Mozilla的官方文档上的关于“Preflighted requests”这段的描述:
第一张图应该是“预检”的请求,它的“Request Method”的确为“OPTIONS”,
而且返回的response的Header中,“Access-Control-Allow-Methods”的值为"GET,PUT,DELETE",并未包含“POST”,所以理论上POST请求应该是无法发送的才是。
但是,从第二张图来看,POST类型的请求仍然被发送了。这是怎么回事呢?想不通。
PS:我使用 Chrome、Firefox、Safari测试了,都是同样的结果。
追加
或者说,我想实现在跨域的时候,禁止客户端使用POST请求,要怎么设置才行呢?
添加测试代码
实现 CORS的filter
/**
* Servlet Filter implementation class CorsFilter
*/
@WebFilter("/*")
public class CorsFilter implements Filter {
/**
* Default constructor.
*/
public CorsFilter() {
}
/**
* @see Filter#destroy()
*/
public void destroy() {
}
/**
* @see Filter#doFilter(ServletRequest, ServletResponse, FilterChain)
*/
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain)
throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) resp;
String currentOrigin = request.getHeader("Origin");
response.setHeader("Access-Control-Allow-Origin", "*");
response.setHeader("Access-Control-Allow-Methods", "GET,PUT,DELETE");
response.setHeader("Access-Control-Allow-Headers", "Content-type");
// response.setHeader("Access-Control-Allow-Headers", "xxx");
chain.doFilter(req, resp);
}
/**
* @see Filter#init(FilterConfig)
*/
public void init(FilterConfig fConfig) throws ServletException {
}
}
测试用的 ajax
$.ajax({
"type" : "POST",
"url" : "http://ip:port/bcdae/v1/user/file/1",
"contentType" : "application/json",
"data" : JSON.stringify({
"id" : "123",
"text" : "test"
}),
"success" : function(msg){
$("#corsRes").text(msg);
}
});
火狐也是如此行为。因为标准是这么说的:
simple method 是指 GET, HEAD 或者 POST。所以这三个方法是例外的。Google 搜索时也可以观察到人们只遇到了因为这个头导致 delete 啊 put 啊 patch 啊之类的被拒绝的情况。
服务端如果不同意 POST 的话,可以不允许对应的 Origin,或者返回 403 啊什么的都可以的吧。(标准读起来好枯燥啊 :-( )
PS: 死 markdown 我明明写的「7.」,它非要给我改成「1.」,所以只好写汉字了……