Access-Control-Allow-Origin和反向代理处理跨域
什么是跨域
跨域,指的是浏览器不能执行其他网站的脚本。它是由浏览器的同源策略造成的,是浏览器对javascript施加的安全限制。
所谓同源是指,域名,协议,端口相同。浏览器执行javascript脚本时,会检查这个脚本属于那个页面,如果不是同源页面,就不会被执行。
同源策略的目的,是防止黑客做一些做奸犯科的勾当。比如说,如果一个银行的一个应用允许用户上传网页,如果没有同源策略,黑客可以编写一个登陆表单提交到自己的服务器上,得到一个看上去相当高大上的页面。黑客把这个页面通过邮件等发给用户,用户误认为这是某银行的主网页进行登陆,就会泄露自己的用户数据。而因为浏览器的同源策略,黑客无法收到表单数据。
现在随着RESTFUL的流行,很多应用提供http/https接口的API,通过xml/json格式对外提供服务,实现开放架构。如,微博、微信、天气预报、openstack等网站和应用都提供restful接口。
Web应用也在向单页面方向发展。越来越多的web应用现在是这样的架构:
静态单个web页面
ajax调用
RESTFUL服务
我们本可以利用各个网站提供的API,做出很多精彩的Web应用。但浏览器执行javascript时的跨域限制,就成为了这类开放架构的拦路虎。
为了解决跨域请求的问题,我们需要在web应用中设置跨域的过滤器来实现,在web.xml总配置。在Springmvc框架中自定义过滤器filter,并能解决 Content-Type为application/json时跨域不通过的问题。
<filter>
<filter-name>corsFilter</filter-name>
<filter-class>com.x.x.CorsFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>corsFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
同样的过滤代码
public class CorsFilter implements Filter {
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
HttpServletResponse response = (HttpServletResponse) res;
response.setHeader("Access-Control-Allow-Origin", "*");
response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, HEAD, DELETE, PUT");
response.setHeader("Access-Control-Max-Age", "3600");
response.setHeader("Access-Control-Allow-Headers",
"X-Requested-With, Content-Type, Authorization, Accept, Origin, User-Agent, Content-Range, Content-Disposition, Content-Description");
chain.doFilter(req, res);
}
public void init(FilterConfig filterConfig) {}
public void destroy() {}}
这样设置过滤器就可以很方便的绕过ajax请求jsonp的跨域请求。
SpringMVC开启CORS支持
之前我们跨域是借助了浏览器对 Access-Control-Allow-Origin 的支持。但有些浏览器是不支持的,所以这并非是最佳方案
现在我们来利用nginx 通过反向代理 满足浏览器的同源策略实现跨域
首先,我先注释掉之前的跨域设置
然后我们回到nginx.conf 配置一个反向代理路径(新增红色部分)
server {
listen 8094;
server_name localhost;
#charset koi8-r;
#access_log logs/host.access.log main;
location / {
root html;
index index.html index.htm;
}
location /apis {
rewrite ^.+apis/?(.*)$ /$1 break;
include uwsgi_params;
proxy_pass http://localhost:1894;
}}
配置说明:配置一个/apis 重写到我们真正的api地址http://localhost:1894 形成一个代理的过程。
然后更改一下index1.html的api请求地址.
这样这个api的地址就跟当前页面index1.html处于同源位置了。就是我们配置的nginx监听地址 localhost:8094
然后我们再次在浏览器中访问 index1.html 可能请求到的知识缓存页面 请清除缓存或重启nginx
具体详见: