最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • 跨域

    正文概述 掘金(isisxu)   2021-04-06   809

    写在前面

    跨域概念:跨域是指一个域下的文档或脚本试图去请求另一个域下的资源(比如从a站点获取一个页面,然后在这个页面上去访问b站点的资源,就会发生跨域)

    同源相同协议,相同域名,相同端口三者相同被称为同源;反之不同源;同源情况下就不存在跨域了。即便两个不同的域名指向同一个ip地址,也非同源。

    同源是浏览器最核心也最基本的安全功能,如果缺少了同源策略,浏览器很容易受到XSS、CSFR等攻击

    同源限制

    1.) Cookie、LocalStorage 和 IndexDB 无法读取
    2.) DOM 和 Js对象无法获得
    3.) AJAX 请求不能发送
    

    备注:浏览器对通过script标签访问其他域名是没有限制的。(比如平时jquery库的引入,就是script标签跨域,但是浏览器没有限制)

    // 跨域示例
    客户端以XMLHttpRequest对象访问`http://www.tianmao.com`, 天猫返回给客户端,
    在`http://www.tianmao.com`域名网页中,有一端js代码请求`http://www.jd.com`,
    这时候请求京东网址,会发生跨域,因为浏览器有安全限制,请求发出去,但是数据回不来;
    浏览器对XMLHttpRequest对象跨域请求有限制,但是对script标签没有限制
    

    跨域9种解决方案

    1、 通过jsonp跨域(script标签跨域)
    2、 document.domain + iframe跨域
    3、 location.hash + iframe
    4、 window.name + iframe跨域
    5、 postMessage跨域
    6、 跨域资源共享(CORS)
    7、 nginx代理跨域(中间server转发)
    8、 nodejs中间件代理跨域(中间server转发)
    9、 WebSocket协议跨域(新协议不受跨域限制)
    

    跨域鼻祖

    最开始针对跨域,需要人为手动修改host。比如当前端本地请求的后端的数据接口是http:api.xx.com/getData,但是本地浏览器直接访问会跨域;此时可以在本地起一个web服务地址http:127.0.0.1:1111/index.html,然后修改host文件,使得前端代码中请求api.xx.com接口时,让请求打到127.0.0.1:1111服务地址上。这样让本地服务器去访问远程服务器就不会发生跨域,因为跨域不存在后端服务器之间

    jsonp

    jsonp的底层原理:通过script标签发送请求,利用 <script> 标签没有跨域限制的漏洞

    跨域

    jsonp跨域弊端

    1. 只支持get请求方式。因为它是使用script标签去发送请求的;而且服务器端需要做处理,客户端也需要做处理;如果跨域时传递的参数非常多,那么这种方式不可取。
    2. 不安全。server返回的是浏览器直接执行的func("data"),不管返回什么,浏览器都会直接执行,如果返回的是木马程序,那。。。。;而且数据是通过url的问号传参的方式,很容易被url劫持。

    jsonp优点: 兼容性好,可用于解决主流浏览器的跨域数据访问的问题

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

    <!-- 示例1:此时服务器是返回数据了,但是报错语法错误SyntaxError,因为我们是以script的方式请求的,所以服务器返回的数据,客户端就会以js的方式去解析 -->
    <script>
        document.querySelector('input').onclick = function(){
            var script = document.creatElement("script");
            script.src = "http://www.jd.com/index.php";
            document.body.appendChild(script);
        }
    </script>
    
    <!-- 示例2:可以将客户端的回调函数作为参数传递给服务器端,让服务器端返回函数调用的字符串形式 -->
    <script>
        function getInfo(data){
            // 处理服务器返回数据
            console.log(data);
        }
        document.querySelector('input').onclick = function(){
            var script = document.creatElement("script");
            script.src = "http://www.jd.com/index.php?callback=getInfo";   // 需要服务器返回 "getInfo(返回数据)" 这样客户端就可以以js代码解析成函数调用处理
            document.body.appendChild(script);
        }
    </script>
    

    CORS跨域资源共享

    普通跨域请求:只服务端设置Access-Control-Allow-Origin即可,前端无须设置,若要带cookie请求:前后端都需要设置。

    需注意的是:由于同源策略的限制,所读取的cookie为跨域请求接口所在域的cookie,而非当前页。

    兼容性:目前,所有浏览器都支持该功能(IE8+:IE8/9需要使用XDomainRequest对象来支持CORS)),CORS也已经成为主流的跨域解决方案。

    CORS跨域原理:比如客户端在127.0.0.1:5000/index.html页面访问服务端127.0.0.1:3000地址,此时发生跨域,服务端可以在响应头中,设置Access-Control-Allow-Origin:127.0.0.1:5000,允许127.0.0.1:5000这个地址的客户端访问自己。

    注意点:在cors跨域方式中,客户端会向服务端先进行一次options试探性请求,服务端看到这个请求,会返回表示同意接下来的跨域请求。

    步骤要点

    1. 客户端(ajax/fetch发送请求)
    
    2. 服务端设置相关头信息(比如允许跨域的域名,允许跨域的方法,允许跨域的cookie凭证)
    
    3. 服务端还需要处理options试探性请求
    

    缺点:

    1. Access-Control-Allow-Origin只能设置成 * / 一个具体的域名地址,;如果设置成*号就不能携带cookie。 因为所有的源都能请求,cookie被传来传去的,浏览器为了保证安全性,所以不允许携带cookie。

    http-proxy

    一般在webpack、webpack-dev-server中配置; 代理的思想基本都是起一个中间webserver,前端先把请求打到webserver上,然后webserver再请求后端;因为服务到服务之间不存在跨域。

    // src/client.js
    // 模拟测试client
    // 注意这里默认请求的是 http://localhost:8080,但是server.js中启动的是http://localhost:3000,所以跨域了访问不到,
    // 提供思路,可以先让client把请求发到webpack的devServe上,devServer是http://localhost:8080服务,然后再让devServer转发到server.js的http://localhost:3000服务上
    let xhr = new XMLHttpRequest()
    xhr.open('GET', '/api/user', true)
    xhr.onload = () => {
      console.log(xhr.response);
    }
    xhr.send()
    
    
    // src/server.js 
    let express = require('express')
    let app = express()
    
    app.get('/api/user', (req, res) => {
      res.send("我是服务端的返回信息hello")
    })
    app.listen(3000, '127.0.0.1')  // 这里的ip可以省略,默认监听的localhost
    
    
    
    // webpack.config.js
    devServer: {
      proxy: {
        '/api': 'http://localhost:3000'   // 给devServe配置代理,devServer不设置port默认在8080启动,这里表示对http://localhost:8080域名下以/api开头的,会被代理到http://localhost:3000 域名下
      }
    }
    

    nginx反向代理

    比如本地访问后端的地址是www.xxx.com/api,但是可能会发生跨域,可以在本地搭个nginx,在nginx中搭个代理服务,然后让本地服务直接请求ng代理服务,然后ng代理服务再把请求转发给远程服务器。

    // client.js
    正常请求远程服务: www.xxx.com/api
    
    将本地代码请求修改为ng监听地址: `127.0.0.1:80/api`,这样就访问到ng,然后打到 `locaiotn /api/`,ng代理的服务就会去请求`http:www.xxx.com/api`
    
    
    // 在本地配置nginx.conf
    server: {
        listen:80
        server_name: 127.0.0.1
    
        locaiotn /api/ {
            proxy_pass   http:www.xxx.com/api
        }
    }
    

    postMessage

    webSocket

    juejin.cn/post/684490…

    www.ruanyifeng.com/blog/2017/0…

    初次接触 WebSocket 的人,都会问同样的问题:我们已经有了 HTTP 协议,为什么还需要另一个协议?它能带来什么好处?

    答案很简单,因为 HTTP 协议有一个缺陷:通信只能由客户端发起,不能从服务端推送数据到客户端;websocket就是一种不仅能从客户端发送数据到服务端,也可以主动从服务的推送数据给客户端的一种全双工通信协议。

    websocket是一种网络通信协议,使用ws://(非加密)和wss://(加密)作为协议前缀,浏览器对这种通信协议没有跨域限制。

    // websocket特点
    (1)建立在 TCP 协议之上,服务器端的实现比较容易。
    (2)与 HTTP 协议有着良好的兼容性。默认端口也是80和443,并且握手阶段采用 HTTP 协议,因此握手时不容易屏蔽,能通过各种 HTTP 代理服务器。
    (3)数据格式比较轻量,性能开销小,通信高效。
    (4)可以发送文本,也可以发送二进制数据。
    (5)没有同源限制,客户端可以与任意服务器通信。
    
    ws://example.com:80/some/path
    

    跨域

    // client.js
    
    // 执行new WebSocket("wss://echo.websocket.org")就会去连接wss://echo.websocket.org服务器。
    var ws = new WebSocket("wss://echo.websocket.org");
    
    // 成功的回调
    ws.onopen = function(evt) { 
      console.log("Connection open ..."); 
      ws.send("Hello WebSockets!");
    };
    
    ws.onmessage = function(evt) {
      console.log( "Received Message: " + evt.data);
      ws.close();
    };
    
    ws.onclose = function(evt) {
      console.log("Connection closed.");
    };      
    

    起源地下载网 » 跨域

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元