CORS
原理:Cross-Origin Resource Sharing ,即跨源资源共享,在现代版浏览器上,增加一些新的请求头和响应头,浏览器通过这些请求头和响应头,判断是否允许我们跨域访问,以及允许的访问的时间,允许访问的网站等等。
案例:
a域:html
<input type="button" onclick="btnClick" value="请求资源"/>
a域:前端js
<script src="/javascripts/jquery.js" type="text/javascript"></script> <script type="text/javascript"> //按钮点击事件 function btnClick(){ //发送ajax请求到b域获取资源 $.get("http://www.b.com/getData",function(data){ alert(data); }); } </script>
b域:后端代码(java)
@RequestMapping(value = "/getData", method=RequestMethod.GET) @ResponseBody public String getData(HttpServletResponse response ) throws IOException{ //设置响应头,允许所有网站跨域访问本资源 response.setHeader("Access-Control-Allow-Origin", "*"); //只允许www.a.com访问本资源 // response.setHeader("Access-Control-Allow-Origin", "http://www.a.com"); return "success"; }
流程:
1.a域的用户点击按钮后,发送ajax请求到b域获取资源
2.b域设置响应头"Access-Control-Allow-Origin",值为"*",表示允许所有网站跨域访问资源,然后返回资源
3.a域的用户的浏览器接收b域返回的资源后,判断响应头"Access-Control-Allow-Origin"中设置的值是否允许a域访问,因为此时为"*",表示允许访问,浏览器将b域的资源放行,a域获取到资源
优点:1.充分利用现代浏览器的特性,配置最少,方便维护2支持所有类型的http请求缺点:1.有些低版本的浏览器不兼容该特性,如IE6,IE7其他:cors是最推荐的使用跨域的解决方案,其充分利用现代浏览器的新特性,使用相对来说比较少的配置,就可以在支持所有类型的http请求下达到跨域的效果,但如果目标用户的浏览器比较原始,就需要权衡一下该方案,以下图片为支持cors的浏览器,绿色表示支持cors,该信息统计为2014年,最新统计请参考戳我,关于cors的其他请求头和响应头请参考戳我其他解决方案:现在主流推荐的是使用cors解决跨域问题,之所有会出现跨域,是因为现代的浏览器在通过ajax访问非本域的资源成功后,不会直接将资源返还给本域,在这之前,会判断一下ajax发送方的域名与请求的资源所在的域是否匹配,匹配则放行,如果不匹配,会去判断响应头中,是否包含"Access-Control-Allow-Origin",且进一步去判断该响应头对应的值是否与ajax发送方的域名匹配,只有在匹配的情况下,才会将资源放行,具体流程如下
所以我们的解决思路是
1取消浏览器的安全检查:
chrome通过命令屏蔽跨域安全检查
2在响应头中加上Access-Control-Allow-Origin允许跨域访问:
tomcat设置过滤器
nginx设置响应头
chrome通过插件实现跨域
chrome通过命令屏蔽跨域安全检查
可参考戳我, 如果添加–disable-web-security无效的话,重启下浏览器并确保所有chrome后台进程已被关闭,重启后再次访问就可以了
tomcat设置过滤器
创建过滤器
package com.filter; import javax.servlet.*; import javax.servlet.http.HttpServletResponse; import java.io.IOException; /** * Created by zhangyajun */ public class CORSFilter implements Filter { @Override public void init(FilterConfig filterConfig) throws ServletException { } @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { HttpServletResponse httpResponse = (HttpServletResponse) servletResponse; //此处*代表允许所有域名跨域,也可以指定具体的域名,多个域名用","隔开 httpResponse.addHeader("Access-Control-Allow-Origin", "*"); //设置允许www.b.com和www.c.com跨域 //httpResponse.addHeader("Access-Control-Allow-Origin", "http://www.b.com,http://www.c.com"); filterChain.doFilter(servletRequest, servletResponse); } @Override public void destroy() { } }
web.xml配置:注意配置顺序,CorsFilter过滤器放在最前面
<!--允许跨域过滤器--> <filter> <filter-name>CorsFilter</filter-name> <filter-class>com.filter.CORSFilter</filter-class> </filter> <filter-mapping> <filter-name>CorsFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
nginx设置响应头
location / {
add_header Access-Control-Allow-Origin *;
}
这样在所有的响应头上会默认加上Access-Control-Allow-Origin *,允许所有域名跨域访问
chorme通过插件实现跨域
下载戳我插件,安装到chrome的拓展程序中,该插件会自动添加响应头Access-Control-Allow-Origin *,从而达到跨域效果,在测试时方便使用。
转载于:https://blog.51cto.com/simplelife/1886843