Web开发中的跨域问题

本文为我在web开发中遇到的跨域问题的踩坑总结。


关于跨域

由于显而易见的安全原因,浏览器会阻止从一个域上加载的脚本获取或操作另一个域上的文档属性。也就是说,受到请求的 URL 的域必须与当前 Web 页面的域相同。例如默认情况下,浏览器不允许一个其它域名下的网站通过ajax调用你自己写的接口。这固然增加网站的安全性,但也给前端开发测试甚至上线造成麻烦。本地测试时无法调用服务器接口,部署在其它域名下的页面无法正常使用服务……


解决方法:

仅在本地测试时跨域

这个就非常好解决了。如果本地开发使用chrome浏览器,那么只需要在启动chrome浏览器时加上如下参数:

google-chrome-stable --args --disbale-web-security ./index.html

如果你在Windows环境下开发,更右击桌面图标,在属性中也能更改启动参数。更改参数后浏览器会不再拦截跨域行为。


JSONP跨域

我们知道,浏览器不会对 <script> 标签做跨域限制。这也我就能在页面中通过形如 <script src=“http://www.example.com/api?js=2333" ></script> 的方式跨域请求。当然这有很多限制,比如它只能做GET请求,而且之所以有这也的跨域方式存在,主要还是由于一些历史遗留问题。如果是自己做开发的话,不是很推荐这种方式解决跨域问题。


服务器端解决跨域

这应该是比较彻底的解决方法了。直接在服务器的响应头上添加参数,允许浏览器进行跨域请求的操作。比如我可以配置nginx在Response Header上增加如下参数

add_header 'Access-Control-Allow-Origin' '*';
add_header 'Access-Control-Allow-Credentials' 'true';
add_header 'Access-Control-Allow-Methods' 'OPTION, POST, GET';
add_header 'Access-Control-Allow-Headers' 'X-Requested-With, Content-Type';

‘Access-Control-Allow-Origin’限制了能够跨域调用的域名。如果想要让任意域名调用,留为*即可。而Access-Control-Allow-Credentials则是打开了跨域访问。Access-Control-Allow-Methods限制了跨域调用能够使用的HTTP方法。请求后可以查看到信息:

还有很多Web框架,比如Flask,Spring都提供了跨域请求的解决方案。不过原理不外乎是对Response Header的修改。