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

什么是跨域

跨域,指的是浏览器不能执行其他网站的脚本。它是由浏览器的同源策略造成的,是浏览器对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. NGUI系列教程五(角色信息跟随)

    在一些网络游戏中,我们常常可以看到角色的上方显示着角色的名称,等级,血量等信息.它们可以跟随角色移动,并且可以显示和隐藏.今天我们就来学习一下这些功能的实现方法.1. 新建unity工 程,导入NGU ...

  2. Lucene基础(一)--入门

    Lucene介绍 lucene的介绍,这里引用百度百科的介绍Lucene是apache软件基金会4 jakarta项目组的一个子项目,是一个开放源代码的全文检索引擎工具包,即它不是一个完整的全文检索引 ...

  3. POJ3613 Cow Relays [矩阵乘法 floyd类似]

    Cow Relays Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 7335   Accepted: 2878 Descri ...

  4. 如何学习C++[转]

    关于学C++, 我向你推荐一些书(当然能够结合课内项目实践更好) 1.The C++ Programming Language(Bjarne Stroustrup)2. Inside The C++ ...

  5. import information website

    1. 一个很好的展示如何review paper和response to reviewer的网站:openview 该网站给出了许多paper review的例子(如何你是reviewer,那么可以参 ...

  6. 【产品体验】eyepetizer开眼

    第一次写博客,内心还有点小激动呢~~本人产品新人,学习中,希望大家多多指教!  先来两张开眼的界面图坐镇——         开眼简介: appetizer for eyes 即 eyepetizer ...

  7. icon在线编辑和查找工具

    1.www.iconpng.com 2.在线编辑http://www.ico.la/ 3.小图标查找 http://icomoon.io/app/ 4.20个免费的psd http://www.osc ...

  8. Android MediaStore与Media.EXTERNAL_CONTENT_URI

    MediaStore这个类是Android系统提供的一个多媒体数据库,android中多媒体信息都可以从这里提取.这个MediaStore包括了多媒体数据库的所有信息,包括音频,视频和图像,andro ...

  9. 转:HTTP请求(GET、POST和soap区别)和响应

    一直对Http请求和SOAP请求不是太理解,只是知道SOAP是基于Http的,并且增加了很多XML标签,SOAP经常用在WebService中,比如在C#中创建一个WebService,然后在客户端生 ...

  10. plsql 书写命名规范

    俗话说事不预则废,无规矩不成方圆. 对sql脚本程序的设计,个人认为应该是从编码规范开始. 前段时间公司一些同事提交的脚本,风格迥异,让我审核起来倍感难受,丝毫没有审核代码的快感. 特整理了公司部分常 ...