由于 Javascript 同源策略的存在使得一个源中加载来自其它源中资源的行为受到了限制。即会出现跨域请求禁止。

通俗一点说就是如果存在协议、域名、端口或者子域名不同服务端,或一者为IP地址,一者为域名地址(在跨域问题上,域仅仅是通过“ url的首部 ”来识别而不会去尝试判断相同的IP地址对应着两个域或者两个域是否同属同一个IP),之中任意服务端旗下的客户端发起请求其它服务端资源的访问行动都是跨域的,而浏览器为了安全问题一般都限制了跨域访问,也就是不允许跨域请求资源。

但很多时候我们却又不得不去跨域请求资源,这个时候就需要我们想方法去绕过浏览器同源策略的限制了。

常见的跨域请求解决方法:

  1.Jsonp 利用script标签发起get请求不会出现跨域禁止的特点实现

  2.window.name+iframe 借助中介属性window.name实现

  3.html5的 postMessage 主要侧重于前端通讯,不同域下页面之间的数据传递

  4.Cors需要服务器设置header:Access-Control-Allow-Origin

  5.Nginx反向代理 可以不需要目标服务器配合,不过需要Nginx中转服务器,用于转发请求(服务端之间的资源请求不会有跨域限制)

下面分别说一下常用几种解决方案的具体实现:

1 Jsonp

一般情况下由于同源策略我们不能够通过XHR跨域去请求资源,但是我们的script标签却可以不受此限制成功的外链到来自于其他域下的资源。利用script标签这个特点,我们可以成功的绕过同源策略。但这种方式存在局限性,我们只能够发起get跨域请求。具体实现:

客户端

服务端

script标签跨域发起get请求,同时传递在客户端已经注册的全局函数 process_fun 作为查询参数,服务端代码提取查询参数,并传入需要返回的数据。script标签还有一个特点,就是会立即执行调用所请求到的资源,所以这个时候服务端返回的 process_fun(data) 这一句代码会被立即执行,即把数据 data 传入我们事先定义好的函数  process_fun 中执行进一步的处理。

2 Cors

即跨域资源共享。实现cors通信的关键是服务器,只要服务器实现了cors接口,就可以跨源通信。不过不同于jsonp,cors对于IE8以下的浏览器是不支持的。

客户端

服务端

跨域资源共享在我看来是最直接也最简便的解决跨域问题的方式了,唯一的缺陷也就只是不能覆盖支持所有的浏览器。客户端不需要去做另外的改变,跟一般状况下发送的异步请求一致就行,甚至客户端根本不需要知道所请求的接口是跨域的。而服务端所需要做的也只是返回响应的同时设置 Access-Control-Allow-Origin 响应头部,意为“予许指定源(‘*’为任意源)发起跨域资源请求”。

3 window.name 和 postMessage 

window.name 和 postMessage 主要都侧重于纯前端页面之间的数据通讯,前者利用了 “ 在同一浏览器窗口载入的不同页面( 无论它们是否不同域 ),共享同一个window.name,并且都对 window.name 有读写的权限 ” 的这一特性来实现页面间的数据交换,后者则是HTML5的API,不同域下的页面在满足一定关系的条件下可以通过此API跨域传送数据。

4 Nginx反向代理

Nginx反向代理解决跨域问题则是利用了服务端之间的资源请求不会有跨域限制的特点实现的,具体来说就是我们前端发起的请求被Nginx拦截,再由Nginx代由转发请求到资源服务器请求资源。

比如现在我们有两个Nodejs服务,分别是http://127.0.0.1:3000 和 http://127.0.0.1:5000,5000端口对应的服务端下的页面需要发起请求3000端口所对应的服务端的资源,当然,在这种情况下如果不做任何的额外处理,请求会产生跨域。这个时候我们可以用Nginx来代理转发我们的请求,前端不去直接对资源服务器发起请求,而是改为直接访问Nginx服务器,看到这里你可能会问了,发起请求的前端页面是属于 http://127.0.0.1:5000 所在域下的,对Nginx服务发起请求难道不会和之前直接发起的请求一样出现跨域吗?所以这里需要明白的一点是,一开始我们可能是通过 http://127.0.0.1:5000/ 这样的路径访问到我们的页面的,但是如果我们使用Nginx作为反向代理,代理服务器监听8080端口,我们这时候再访问该页面就不再是访问 http://127.0.0.1:5000/ , 而是 http://127.0.0.1:8080/ 了,在Nginx中我们再做这样的配置:

location / {
  proxy_pass http://127.0.0.1:5000;
}

就能成功访问到首页了,而这个时候首页是在 8080 端口所对应的域下(即Nginx服务)被渲染出来的,所以首页这个时候便不再与 http://127.0.0.1:5000 同域, 而是与 Nginx 服务同域了,也就是说前端这时候对 Nginx 服务发起请求就不会再是跨域。

访问 Nginx 我们可以实现了,接下来要做的就是对请求进行代理转发。

前端的 Ajax 请求是这样的:

Nginx 需要对该请求进行拦截,所以可以做如下配置:

location配置的意思是对包含 “cross_origin” 请求拦截,并对请求路径进行重写,一开始请求路径是 “/cross_origin/get_json?type=20170126” ,重写后便成了 “/get_json?type=20170126”,$1代表(.*)中的内容,而(.*)则代表 cross_origin 后面的全部字符,也就是我们会把 cross_origin 部分去掉,但是保留 cross_origin 之后的所有字符,当然这一步并非是绝对必要的。接下来我们再把请求代理到 3000 端口所对应的资源服务,所以请求路径从一开始的 “127.0.0.1:8080/cross_origin/get_json?type=20170126” 经过代理服务器Nginx之后变成了 “127.0.0.1:3000/get_json?type=20170126”。在 “127.0.0.1:3000” 下存在对应的接口:

现在在前端触发点击事件发起请求:

得到了响应,至此我们成功发起了跨域请求。

完。

Nginx反向代理、CORS、JSONP等跨域请求解决方法总结的更多相关文章

  1. 使用nginx反向代理处理前后端跨域访问

    本文主要解决:使用nginx反向代理处理前后端跨域访问的问题 1.何为跨域访问? 以下类型为跨域访问 1)不同域名间访问 www.zuiyoujie.com和www.baidu.com 2)同域名不同 ...

  2. WebApi Ajax 跨域请求解决方法(CORS实现)

    概述 ASP.NET Web API 的好用使用过的都知道,没有复杂的配置文件,一个简单的ApiController加上需要的Action就能工作.但是在使用API的时候总会遇到跨域请求的问题, 特别 ...

  3. WebApi Ajax 跨域请求解决方法(CORS实现)(作者:jianxuanbing)

    概述 ASP.NET Web API 的好用使用过的都知道,没有复杂的配置文件,一个简单的ApiController加上需要的Action就能工作.但是在使用API的时候总会遇到跨域请求的问题,特别各 ...

  4. 客户端ajax请求为实现Token验证添加headers后导致正常请求变为options跨域请求解决方法

    客户端为了实现token认证,通过Jquery的ajaxSetup方法全局配置headers: 全局配置headers后会导致部分不需要token认证的请求变为options请求,导致跨域访问.报错信 ...

  5. 第114天:Ajax跨域请求解决方法(二)

    一.什么是跨域 我们先回顾一下域名地址的组成: http:// www . google : 8080 / script/jquery.js   http:// (协议号)       www  (子 ...

  6. 第113天:Ajax跨域请求解决方法

    一.原生JS实现ajax 第一步获得XMLHttpRequest对象 第二步:设置状态监听函数 第三步:open一个连接,true是异步请求 第四部:send一个请求,可以发送一个对象和字符串,不需要 ...

  7. 跨域请求解决方法(JSONP, CORS)

    1.跨域 假设我们页面或者应用部署在 http://www.aaa.com 上了,而我们打算从 http://www.bbb.com 请求提取数据.一般情况下,如果我们直接使用 AJAX 来请求将会失 ...

  8. Access to XMLHttpRequest at 'XXX' from origin 'XX' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present o AJAX跨域请求解决方法

    今天出现了一个问题找了好久先看代码: 这可能是个BUG吧插入代码: dataType: 'jsonp', crossDomain: true, 最终:

  9. 关于使用Jsonp做跨域请求

    今天在使用Jsonp做跨域请求的练习时碰上这样一个问题 代码如下 <!DOCTYPE html> <html> <head> <meta charset=&q ...

随机推荐

  1. PAT (Advanced Level) 1011. World Cup Betting (20)

    简单题. #include<iostream> #include<cstring> #include<cmath> #include<algorithm> ...

  2. awesome-deep-learning

    https://github.com/ChristosChristofidis/awesome-deep-learning

  3. Ubuntu Server 14.04 & Apache2.4 虚拟主机、模块重写、隐藏入口文件配置

    环境: Ubuntu Server 14.04 , Apache2.4 一.Apache2.4 虚拟主机配置 01. 新建一份配置文件 在apache2.4中,虚拟主机的目录是通过/etc/apach ...

  4. hibernate--多对一单向关联 (重点!!!)

    一个用户组包含多个用户, 每个用户属于一个组. 一个人可以有多个车, 每个车属于一个人. 一个人有很多梦想, 一个特定的梦想属于一个人. 错误做法: person里 有 personid, perso ...

  5. Android Camera 调用流程总结

    1.总体介绍  Android Camera框架从整体上看是一个client/service架构.有两个进程,一个是client进程,可以看成AP端,主要包括Java代码和一些native层的c/c+ ...

  6. JSON串行化

    大多数情况下,我们不会再Javascript中直接创建JSON字符串.而是,创建一些Javascript对象,这些对象和服务器上的.net对象对应.因此,可以在服务器上创建.net实体类,然后串行化成 ...

  7. (简单) POJ 1860 Currency Exchange,SPFA判圈。

    Description Several currency exchange points are working in our city. Let us suppose that each point ...

  8. MFC中PeekMessage的使用,非阻塞消息循环

    在程序设计的时候经常要进行一个数据循环,比如播放音乐需要循环的向缓冲区里面写入数据,在这个时候比较通用的方法是建立一个线程做事情,但是有时候不想创建多线程就可以使用微软提供的PeekMessage方法 ...

  9. FZU 2099 魔法阵

    手算. #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> u ...

  10. vimplugin破解

    必较常用的vi插件有:viplugin.Vrapper.eclim Vrapper没有用过,eclim在公司电脑上装,总是不能正常的连接gvim,所以也没有用 Viplugin,常用功能基本都有... ...