本文作者: 伯乐在线 - 良少 。未经作者许可,禁止转载!
欢迎加入伯乐在线 专栏作者

什么是跨域

跨域,指的是浏览器不能执行其他网站的脚本。它是由浏览器的同源策略造成的,是浏览器对javascript施加的安全限制。

所谓同源是指,域名,协议,端口相同。浏览器执行javascript脚本时,会检查这个脚本属于那个页面,如果不是同源页面,就不会被执行。

同源策略的目的,是防止黑客做一些做奸犯科的勾当。比如说,如果一个银行的一个应用允许用户上传网页,如果没有同源策略,黑客可以编写一个登陆表单提交到自己的服务器上,得到一个看上去相当高大上的页面。黑客把这个页面通过邮件等发给用户,用户误认为这是某银行的主网页进行登陆,就会泄露自己的用户数据。而因为浏览器的同源策略,黑客无法收到表单数据。

现在随着RESTFUL的流行,很多应用提供http/https接口的API,通过xml/json格式对外提供服务,实现开放架构。如,微博、微信、天气预报、openstack等网站和应用都提供restful接口。

Web应用也在向单页面方向发展。越来越多的web应用现在是这样的架构:

静态单个web页面

ajax调用

RESTFUL服务

我们本可以利用各个网站提供的API,做出很多精彩的Web应用。但浏览器执行javascript时的跨域限制,就成为了这类开放架构的拦路虎。

本文提出了一种简单有效的方式解决跨域问题。

常用的跨域方法

常用的跨域方法有这样一些:

1,使用iFrame访问另一个域。 然后再从另一个页面读取iFrame的内容。jquery等有一些封装。据说Firefox等可能不支持读取另一个iFrame的内容。

2,jsonp。需要服务器支持。使用script src动态得到一段java代码。是回调页面上的js函数,参数是一个json对象。jquery也有封装。

3,设置http头,Access-Control-Allow-Origin:*但据说IE有一些版本不识别这个http头。

4,服务器代理。如,服务器写一个url的处理action。其参数是一个url。这个服务器会用参数拼凑一个url,用httpclient库去执行url,然后把读取的内容再输出到http客户端。

nginx反向代理实现跨域

上面提到的这些跨域方法,都有一些问题。有的不能支持所有浏览器,有的需要修改javascript代码,有的需要重写服务器端代码。有的在session等场景下会有问题。

其实,用nginx反向代理实现跨域,是最简单的跨域方式。只需要修改nginx的配置即可解决跨域问题,支持所有浏览器,支持session,不需要修改任何代码,并且不会影响服务器性能。

我们只需要配置nginx,在一个服务器上配置多个前缀来转发http/https请求到多个真实的服务器即可。这样,这个服务器上所有url都是相同的域名、协议和端口。因此,对于浏览器来说,这些url都是同源的,没有跨域限制。而实际上,这些url实际上由物理服务器提供服务。这些服务器内的javascript可以跨域调用所有这些服务器上的url。

下面,给出一个nginx支持跨域的例子,进行具体说明。

如,我们有两个pythonflask开发的项目:testFlask1和testFlask2。

testFlask2项目上的javascript脚本要通过ajax方式调用testFlask1的一个url,获取一些数据。

正常情况下部署,就会有跨域问题,浏览器拒绝执行如下这样的调用。

 
 
1
2
3
4
5
6
$("button").click(function(){
   $.get("127.0.0.1:8081/partners/json",
   function(result){
      $("div").html(result);
   });
});

下面把testFlask2项目的javascrip文件修改一下。这样访问同源的url,就不会有跨域问题。

 
 
1
2
3
4
5
6
7
8
9
$("button").click(function(){
 
$.get("partners/json",
function(result){
 
$("div").html(result);
 
});
});

但是,我们testFlask2项目实际上没有partners/json这样的url,那怎么处理呢?

我们这样编写nginx的配置文件:

 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
server{
listen8000;
location/ {
includeuwsgi_params;
 
uwsgi_passunix:/tmp/testFlask2.sock;
}
location/partners {
rewrite^.+partners/?(.*)$ /$1 break;
includeuwsgi_params;
 
uwsgi_passunix:/tmp/testFlask1.sock;
}
 
}

我们把testFlask2项目部署在8080端口的根目录下。把提供web服务的testFlask1项目部署在/partners目录下。

但我们的testFlask1项目并不能处理/partners/json这样的url请求。那怎么办呢?

通过 rewrite^.+partners/?(.*)$ /$1 break; 这一条命令,nginx可以把收到的/partners/*请求全部转为/*请求后再转发给背后的真实web服务器。

这样,RESTFUL的ajax客户端程序,只需要给出特定前缀的url就可以调用任意服务器提供的RESTFUL接口了。

甚至,通过nginx的反向代理,我们还能调用其他公司开发的网站提供的RESTFUL接口。

如,

 
 
1
2
3
4
5
6
location/sohu {
rewrite^.+sohu/?(.*)$ /$1 break;
includeuwsgi_params;
 
proxy_passhttp://www.sohu.com/;
}

我们就把sohu网站整个搬到我们的8080:/sohu/目录下了,我们的javascript就可以尽情调用其RESTFUL服务了。

顺便说一下,rewrite^.+sohu/?(.*)$ /$1 break; 这句命令中,$1表示(.*)这个部分。第一对()内的参数是$1,第二对()内的参数就是$2,以此类推。

总结

本文介绍了利用nginx的反向代理的功能,实现跨域访问任意应用和网站的方法。

nginx是一个高性能的web服务器,常用作反向代理服务器。nginx作为反向代理服务器,就是把http请求转发到另一个或者一些服务器上。

通过把本地一个url前缀映射到要跨域访问的web服务器上,就可以实现跨域访问。

对于浏览器来说,访问的就是同源服务器上的一个url。而nginx通过检测url前缀,把http请求转发到后面真实的物理服务器。并通过rewrite命令把前缀再去掉。这样真实的服务器就可以正确处理请求,并且并不知道这个请求是来自代理服务器的。

简单说,nginx服务器欺骗了浏览器,让它认为这是同源调用,从而解决了浏览器的跨域问题。又通过重写url,欺骗了真实的服务器,让它以为这个http请求是直接来自与用户浏览器的。

这样,为了解决跨域问题,只需要动一下nginx配置文件即可。简单、强大、高效!

最简单实现跨域的方法:用 Nginx 反向代理的更多相关文章

  1. 跨域问题,解决方案-Nginx反向代理

    跨域问题,解决之道 跨域问题,在日常开发过程中,是一个非常熟悉的名词.今天的话题,结合我之前的项目场景,讨论下<跨域问题,解决之道>. 跨域是什么 跨域问题,是由于JavaScript出于 ...

  2. [跨域]跨域解决方法之Ngnix反向代理

    跨域原理:http://www.cnblogs.com/Alear/p/8758331.html 介绍Ngnix之前,我么先来介绍下代理是什么~ 代理相当于中间人,中介的概念 代理分为正向代理和反向代 ...

  3. [转] 最简单实现跨域的方法:使用nginx反向代理

    [From] http://blog.jobbole.com/90975/ 什么是跨域 跨域,指的是浏览器不能执行其他网站的脚本.它是由浏览器的同源策略造成的,是浏览器对javascript施加的安全 ...

  4. AJAX跨域问题解决方法(4)——调用方解决跨域

    调用方解决跨域的方法只有一种,那就是隐藏跨域. 何为隐藏跨域? 隐藏跨域的核心思路是通过反向代理隐藏跨域以欺骗浏览器 什么是反向代理?反向代理是指通过中间服务器使得访问同一个域名的两个不同url最终会 ...

  5. AJAX(XMLHttpRequest)进行跨域请求方法详解(一)

    注意:以下代码请在Firefox 3.5.Chrome 3.0.Safari 4之后的版本中进行测试.IE8的实现方法与其他浏览不同. 跨域请求,顾名思义,就是一个站点中的资源去访问另外一个不同域名站 ...

  6. AJAX跨域问题解决方法(3)——被调用方解决跨域

    被调用方解决跨域是指在HTTP响应头中增加指定的字段,允许调用方调用 可以在两种地方增加1.apache/nginx(HTTP服务器)2.tomcat(应用服务器) 浏览器如何判断跨域?仔细观察可以发 ...

  7. AJAX四种跨域处理方法

    同源策略 同源策略 同源策略限制从一个源加载的文档或者脚本如何与来自另一个源的资源进行交互.这是一个用于隔离潜在恶意文件的关键的安全机制. 具体定义是:一段脚本向后台请求数据,只能读取属于同一协议名. ...

  8. AJAX(XMLHttpRequest)进行跨域请求方法详解

    AJAX(XMLHttpRequest)进行跨域请求方法详解(三) 2010年01月11日 08:48:00 阅读数:24213 注意:以下代码请在Firefox 3.5.Chrome 3.0.Saf ...

  9. JavaScript跨域解决方法大全

    跨域的定义:JavaScript出于安全性考虑,同源策略机制对跨域访问做了限制.域仅仅是通过“URL的首部”字符串进行识别,“URL的首部”指window.location.protocol +win ...

随机推荐

  1. Spring核心框架 - AOP的起源及介绍

    一.AOP技术起源 AOP技术的诞生并不算晚,早在1990年开始,来自Xerox Palo Alto Research Lab(即PARC)的研究人员就对面向对象思想的局限性进行了分析.他们研究出了一 ...

  2. cf Round 601

    A.The Two Routes(BFS) 给出n个城镇,有m条铁路,铁路的补图是公路,汽车和火车同时从1出发,通过每条路的时间为1,不能同时到达除了1和n的其它点,问他们到达n点最少要用多长时间. ...

  3. 数据结构-------单链表(C++)

    相关信息: /** * @subject 数据结构 实验2 * @author 信管1142班 201411671210 赖俊杰 * @project 单链表 * @time 2015年10月29日1 ...

  4. 基于android混合开发的JsBridge技术学习

    1.无JsBridge. js如果要调用java(native.也说原生)方法:则java必须实现js接口供挂载在window对象上供js来执行. 这里简单的可以只调用,调用后java端什么也不做.复 ...

  5. [转载]MongoDB C# 驱动教程

    本教程基于C#驱动 v1.6.x . Api 文档见此处: http://api.mongodb.org/csharp/current/. 简介 本教程介绍由10gen支持的,用于MongoDB的C# ...

  6. 什么是 DevSecOps?系列(一)

    什么是 DevSecOps? 「DevSecOps」 的作用和意义建立在「每个人都对安全负责」的理念之上,其目标是在不影响安全需求的情况下快速的执行安全决策,将决策传递至拥有最高级别环境信息的人员. ...

  7. ***PHP请求服务curl以及json的解析

    对于thinkphp框架,相信每一个php开发者都会有了解或者熟悉吧!前端很多都用的ajax的结合,前几天遇到了一个问题,就是请求另一个服务,也就是请求一个接口,然后对方返回一个json串,一开始对c ...

  8. NSMutableArray,NSMutableDictionary的内存管问题

    今天做项目遇到一个问题,在一个类中定义了一个可变数组,使用的是copy的内存管理策略 当往数组中添加包装好的基本数据的时候,程序直接崩溃了.解决方法:把copy换成strong就不会崩溃了; 后来做了 ...

  9. Codeforces Round #232 (Div. 1)

    这次运气比较好,做出两题.本来是冲着第3题可以cdq分治做的,却没想出来,明天再想好了. A. On Number of Decompositions into Multipliers 题意:n个数a ...

  10. 李洪强实现横向滚动的View<二>

    上一节中我们已经实现了一个带有图片,标题和价格label 的UIView 这节我们用这个view实现一个横向滚动的UIcollectionView 实现的效果如下:  01 - 创建CFTyreScr ...