博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
JavaScript 常用的几种跨域方式实现原理
阅读量:7069 次
发布时间:2019-06-28

本文共 4113 字,大约阅读时间需要 13 分钟。

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

  一、跨域的解决方案

    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.jsvar 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

你可能感兴趣的文章
java 之 Synchronize 锁深度解读(和朋友探讨后的总结和验证)
查看>>
polysh入门
查看>>
mavn打jar包
查看>>
spring @Transactional注解参数详解
查看>>
RDD到底是什么东西(一)
查看>>
Scala类型参数
查看>>
redis缓存java项目中,配置和使用
查看>>
Linux中Mysql主从配置
查看>>
mongodb将副本集转换为切片集群
查看>>
JimStoneAjax使用ANT或者Maven等自动部署工具编译时需要添加debug参数
查看>>
【自用】 Python 信息熵 信息增益
查看>>
Java中BigDecimal的应用
查看>>
DataGrid的itemreader中使用outerDocument
查看>>
理解 JavaScript 的函数
查看>>
面试题之总结-大数运算
查看>>
我们为什么要使用NOSQL非关系数据库?
查看>>
【转载】QPS、PV 、RT(响应时间)之间的关系
查看>>
PHPdom操作查找xml标签文本
查看>>
git多个公钥
查看>>
java基础
查看>>