JavaScript 常用的几种跨域方式实现原理

前后端进行数据交互的时,会经常碰到请求跨域的问题,以下几种为常见解决方式。

  一、跨域的解决方案

    1、JSONP

      1)原理:利用 script 标签没有跨域限制的漏洞,网页可以得到从其他来源动态产生的 JSON 数据。JSONP 请求一定需要对方的服务器做支持才可以。

      2)JSONP 和 AJAX 对比

         JSONP 和 AJAX 相同,都是客户端向服务器端发送请求,从服务器端获取数据的方式。但 AJAX 属于同源策略,JSONP 属于非同源策略(跨域请求)。

      3)JSONP 优缺点

         JSONP 优点是简单兼容性好,可用于解决主流浏览器的跨域数据访问的问题。缺点是仅支持 get 方法具有局限性,不安全可能会遭受 XSS 攻击。

      4)JSONP 的实现流程

        声明一个回调函数,其函数名(如 show)当做参数值,要传递给跨域请求数据的服务器,函数形参为要获取目标数据(服务器返回的 data)。创建一个script标签,把那个跨域的 API 数据接口地址,赋值给 script 的 src,还要在这个地址中向服务器传递该函数名(可以通过问号传参:?callback=show)。服务器接收到请求后,需要进行特殊的处理:把传递进来的函数名和它需要给你的数据拼接成一个字符串,例如:传递进去的函数名是 show,它准备好的数据是show(我不爱你)。最后服务器把准备的数据通过 HTTP 协议返回给客户端,客户端再调用执行之前声明的回调函数(show),对返回的数据进行操作。在开发中可能会遇到多个 JSONP 请求的回调函数名是相同的,这时候就需要自己封装一个 JSONP 函数(百度上有很多JSONP封装的函数可以搜一下)

      5)jQuery 的 jsonp 形式

        JSONP 都是 GET 和异步请求的,不存在其他的请求方式和同步请求,且 jQuery 默认就会给 JSONP 的请求清除缓存。

        $.ajax({

        url:"[http://crossdomain.com/jsonServerResponse](http://crossdomain.com/jsonServerResponse)",

        dataType:"jsonp",

        type:"get",//可以省略

          jsonpCallback:"show",//->自定义传递给服务器的函数名,而不是使用jQuery自动生成的,可省略

          jsonp:"callback",//->把传递函数名的那个形参callback,可省略

          success:function (data){

           console.log(data);}

         });//相对来说用JQuery的JSONP格式的多一点

    2、CORS

       CORS 需要浏览器和后端同时支持。IE 8 和 9 需要通过 XDomainRequest 来实现。浏览器会自动进行 CORS 通信,实现 CORS 通信的关键是后端。只要后端实现了 CORS,就实现了跨域。服务端设置 Access-Control-Allow-Origin 就可以开启 CORS。 该属性表示哪些域名可以访问资源,如果设置通配符则表示所有网站都可以访问资源。虽然设置 CORS 和前端没什么关系,但是通过这种方式解决跨域问题的话,会在发送请求时出现两种情况,分别为简单请求和复杂请求。

       1)、简单请求

           只要满足以下两大条件就属于简单请求

           条件一:

           GET,POST,HEAD

           条件二:

            Content-Type的值仅限以下三种

          text/plain
          multipart/form-data
          application/x-www-form-urlencoded

          请求中的任意 XMLHttpRequestUpload 对象均没有注册任何事件监听器; XMLHttpRequestUpload 对象可以使用 XMLHttpRequest.upload 属性访问。

      2)、非简单请求

          使用了下面任一 HTTP 方法:

          PUT

                               DELETE

CONNECT

OPTIONS

TRACE

PATCH

Content-Type 的值不属于下列之一:

application/x-www-form-urlencoded

multipart/form-data

text/plain

当发生符合非简单请求(预检请求)的条件时,浏览器会自动先发送一个options请求,如果发现服务器支持该请求,则会将真正的请求发送到后端,反之,如果浏览器发现服务端并不支持该请求,则会在控制台抛出错误,如下:

          假如发送成功,则会在头部多返回以下字段        

Access-Control-Allow-Origin: http://localhost:3001 //该字段表明可供那个源跨域
Access-Control-Allow-Methods: GET, POST, PUT // 该字段表明服务端支持的请求方法
Access-Control-Allow-Headers: X-Custom-Header // 实际请求将携带的自定义请求首部字段

    3、ngnix反向代理      

实现原理类似于 Node 中间件代理,需要你搭建一个中转 nginx 服务器,用于转发请求。

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

实现思路:通过 nginx 配置一个代理服务器(域名与 domain1 相同,端口不同)做跳板机,反向代理访问 domain2 接口,并且可以顺便修改 cookie 中 domain 信息,方便当前域 cookie 写入,实现跨域登录。

先下载nginx,然后将 nginx 目录下的 nginx.conf 修改如下:

// proxy服务器
server {
 listen  80;
 server_name www.domain1.com;
 location / {
  proxy_pass http://www.domain2.com:8080; #反向代理
  proxy_cookie_domain www.domain2.com www.domain1.com; #修改cookie里域名
  index index.html index.htm;
 
  // 当用webpack-dev-server等中间件代理接口访问nignx时,此时无浏览器参与,故没有同源限制,下面的跨域配置可不启用
  add_header Access-Control-Allow-Origin http://www.domain1.com; //当前端只跨域不带cookie时,可为*
  add_header Access-Control-Allow-Credentials true;
 }
}

     最后通过命令行nginx -s reload启动 nginx

     

var xhr = new XMLHttpRequest();`
// 前端开关:浏览器是否读写cookie`
xhr.withCredentials = true;`
// 访问nginx中的代理服务器`
xhr.open('get', '[http://www.domain1.com:81/?user=admin](http://www.domain1.com:81/?user=admin)', true);`
xhr.send();`
// server.js
var http = require('http');
var server = http.createServer();
var qs = require('querystring');
server.on('request', function(req, res) {
 var params = qs.parse(req.url.substring(2));
 // 向前台写cookie
 res.writeHead(200, {
  'Set-Cookie': 'l=a123456;Path=/;Domain=www.domain2.com;HttpOnly' // HttpOnly:脚本无法读取
 });
 res.write(JSON.stringify(params));
 res.end();
});
server.listen('8080');
console.log('Server is running at port 8080...');             

总的来说,使用CORS简单请求,非常容易,对于前端来说无需做任何配置,与发送普通ajax请求无异。唯一需要注意的是,需要携带cookie信息时,需要将withCredentials设置为true即可。CORS的配置,完全在后端设置,配置起来也比较容易,目前对于大部分浏览器兼容性也比较好。CORS优势也比较明显,可以实现任何类型的请求


转载:https://my.oschina.net/u/3972188/blog/3009785

      

转载于:https://www.cnblogs.com/HoldSelf/p/10442010.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值