同源策略与跨域问题

在先后端通讯时,有时会遇到跨域问题,接下来将从如下几个方面进行跨域详解。javascript

1. 为何会有跨域问题?java

2. 什么是同源策略?jquery

3.先后端通讯方式有哪些?web

4.解决跨域通讯的方式有哪些?ajax

5.解决跨域方式详细说明express

 

为何会有跨域问题?json

  答:是因为浏览器的同源策略。后端

什么是同源策略?api

  答:同源策略(Same origin policy)是一种约定,它是浏览器最核心也最基本的安全功能。 同源策略限制了从一个源加载的文件或脚本如何与另外一个源的资源进行交互。这是一个用于隔离潜在恶意文件的安全机制。跨域

  那什么是源呢?源就是由:协议 + 域名 + 端口号  组成;

  只有同源的时候才能够完成通讯;若是是非同源的话,浏览器会在控制台中报一个异常,提示拒绝访问。

  同源策略的限制:

    一、cookie,localstorage和IndexDB没法读取;

    二、DOM没法获取;

    三、Ajax请求不能发送

先后端通讯方式有哪些?

  答:ajax;  webSocket;  CORS(跨域资源共享)

解决跨域通讯的方式有哪些?

  答:jsonp;  webSocket;  CORS;   Hash;  postMessage;  

解决跨域方式详细说明

 1--jsonp

  原理:利用<script>元素的开放策略,能够加载其余源的文件和动态产生的json,可是JSONP请求必定要对方的服务器支持才可使用。

  具体写法:

    第一种跟第三种写法的原理是同样的,都是利用script标签,建立回调函数fn,把那个跨域的api接口地址赋给script的src,并把新建的函数做为参数传递给接口(?callback=fn),后端接受请求后,会把传进来的函数名fn和查询到的数据组合(fn({data:“张三”}))后返回;

    第二种写法是利用jQuery的jsonp请求,在ajax请求时指定服务器返回的数据类型,可是jsonp只支持get请求,不支持post;

 <!-- 客户端 -->
    <script>
        function call(data){ alert(data) } // 第一种:动态添加script标签
        function createScript(src){ var script = document.createElement("script"); script.setAttribute("type","text/javascript"); script.src = src; document.body.appendChild(script); } createScript("http://127.0.0.1:3000/?callback=call"); // 第二种:jquery的jsonp方式
 $.ajsx({ url: "http://127.0.0.1:3000/", type: "GET",      //jsonp只支持get请求,不支持post
            dataType: "jsonp",  //指定服务器返回的类型
            success: function(data){ console.log(JSON.stringify(data)); } }) </script>
    <!-- 第三种:直接使用script标签 -->
    <script type="text/javascript" src="http://127.0.0.1:3000?callback=call"></script>

<!-- 服务端 --> app.get('/',function(req,res){ var callback = req.query.callback; var data = {nama:"Marry"}; res.send(callback+"("+data+")"); res.end(); }); 

 

2--webSocket

  WebSocket 简介:

    是 HTML5 开始提供的一种在单个 TCP 链接上进行全双工通信的协议。

    WebSocket使得客户端和服务器端的通讯更加方便,容许服务端主动向客户端返回数据,使用WebSocket,客户端和服务器端只需创建一次“握手”,就能够创建永久链接,并进行双向数据请求。

  WebSocket的写法:

 // 浏览器发出的WebSocket请求的头信息。
        GET /chat HTTP/1.1     
        Host: server.example.com    
        Upgrade: websocket       //Upgrade 字段必须设置 Websocket,表示但愿升级到 Websocket 协议。
        Connection: Upgrade    //Connection 必须设置 Upgrade,表示客户端但愿链接升级。
        Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw==
        Sec-WebSocket-Protocol: chat, superchat
        Sec-WebSocket-Version: 13   //表示支持的 Websocket 版本
        Origin: http://example.com     //表示在浏览器中发起此 Websocket 链接所在的页面

   浏览器请求头中有“Origin”,表示发起链接的源,正是因为有这个字段,才能够进行非同源通讯,服务器接收到请求后,会根据这个字段判断是否容许通讯,若是该地址在容许的通讯的名单中,则服务器会返回如下信息。

// 服务器回应
    HTTP/1.1 101 Switching Protocols
    Upgrade: websocket
    Connection: Upgrade
    Sec-WebSocket-Accept: fFBooB7FAkLlXgRSz0BT3v4hq5s= Sec-WebSocket-Location: ws://example.com/

  

3--CORS

  CORS简介:

    CORS全称是“跨域资源共享”,它容许浏览器向不一样源(协议+域名+端口号)的服务器发送XMLHttpRequest请求,从而解决了ajax只能同源访问的限制。

    CORS须要客户端和服务器都配置才能够正常使用,CORS的通讯与Ajax通讯对于开发者来讲代码都是同样的,只是当浏览器识别到是Ajax请求时,会自动给请求的头信息里增长一些信息,但用户是发觉不到的。

  所以,实现CORS通讯的关键是服务器端的接口要支持CORS,只要实现了CORS接口,就能够进行跨域通讯了。

  CORS写法:

 // 服务器端设置
    var express = require('express');
    var app = express();
    var allowCrossDomain = function (req, res, next) {
        res.header('Access-Control-Allow-Origin', 'http://localhost:3001');
        res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE');
        res.header('Access-Control-Allow-Headers', 'Content-Type');
        next();
    }
    app.use(allowCrossDomain);

 

  CORS参数介绍:

    Access-Control-Allow-Methods:该字段必需,它的值是逗号分隔的一个字符串,代表服务器支持的全部跨域请求的方法。注意,返回的是全部支持的方法,而不单是浏览器请求的那个方法。这是为了不屡次"预检"请求。

    Access-Control-Allow-Origin:该字段必填。它的值要么是请求时Origin字段的具体值,要么是一个*,表示接受任意域名的请求。

    Access-Control-Expose-Headers:该字段可选。CORS请求时,XMLHttpRequest对象的getResponseHeader()方法只能拿到6个基本字段:Cache-Control、Content-Language、Content-Type、Expires、Last-Modified、Pragma。若是想拿到其余字段,就必须在Access-Control-Expose-Headers里面指定。

  注意事项:

    使用cors时须要传递cookie,虽然能够跨域通讯,但cookie依然遵循同源策略,只有用服务器设置的cookie才能够获取到并上传,其余域名的不能够。

 

4--Hash

  Hash写法:

// 当前页面A经过iframe或者frame嵌入了页面B,经过hash实现A、B页面通讯
    //A中代码
    var B = document.getElementsByTagName('iframe');
    var data = JSON.stringify({name:"zhangsan"})
    B.src = B.src + data;//data是要传递的参数,已转换成字符串
    //B中代码
    window.onhashchange = function(){//经过onhashchange监听hash的变化
        var dataVal = window.location.hash;
    }

 

  Hash主要是利用onhashchange 这个事件监听hash的变化,来获取传递的参数。

 

5--postMessage

  postMessage简介:

    在HTML5中新增了postMessage方法,postMessage能够实现跨文档消息传输(Cross Document Messaging),Internet Explorer 8, Firefox 3, Opera 9, Chrome 3和 Safari 4都支持postMessage。

    该方法能够经过绑定window的message事件来监听发送跨文档消息传输内容。
  postMessage写法:
    //窗口A(http://a.com)向跨域的窗口B(http://b.com)通讯
    //A中代码
    a.postMessage("data","http://b.com");//第一个参数为要传递的数据;第二个参数是要通讯的源。
    //B中代码
    b.addEventListener("message", function(event){
        console.log(event.origin,event.source,event.data)//能够获取到发送消息的源,发送消息的窗口对象,还有传递的数据
    })

  postMessage主要是用postMessage方法和message事件相结合完成跨域通讯的。

 

以上就是同源策略和跨域通讯的相关解释,有不对的地方,欢迎你们指正

 

-THE END-

相关文章
相关标签/搜索