Web跨域请求及其解决方案

目录

一、理论概述

1. 什么是跨域请求(Cross-domain Request)

2. 浏览器的同源策略(Same-origin Policy)

3. 存在的安全风险

4. CSRF攻击简介

二、跨域方案

1. 跨域资源共享(CORS)

(1)CORS简单请求

(2)CORS非简单请求(也称预检请求)

HTTP 响应首部字段

Access-Control-Allow-Origin

Access-Control-Expose-Headers

Access-Control-Max-Age

Access-Control-Allow-Credentials

Access-Control-Allow-Methods

Access-Control-Allow-Headers

HTTP 请求首部字段

Origin

Access-Control-Request-Method

Access-Control-Request-Headers

规范

浏览器兼容性

2. JSONP请求

3. JSONP和CORS请求比较

4.子域跨父域

5. iframe跨父窗口

6. window.postMessage

7. 使用代理避开跨域请求


一、理论概述

1. 什么是跨域请求(Cross-domain Request)

​        在 HTML 中,,

, ,

        大家可能注意到,JQuery是怎么实现返回数据的?其实,在JQuery的JSONP实现中,首先将你在success中定义的函数封装成jsonpCallback定义的函数,然后再封装一个脚本请求如

3. JSONP和CORS请求比较

        JSONP请求,缺点是仅支持GET请求,必须完全信任提供服务的第三方,优点是支持老式浏览器,兼容性较好。

        CORS比JSONP更强大,支持所有类型的HTTP请求。

4.子域跨父域

        子域跨父域是支持的,但是需要显式将子域的域名改成父域的,例如mail.mysite.com要请求mysite.com的数据,那么在mail.mysite.com脚本里需要执行:

document.domain = "mysite.com";

5. iframe跨父窗口

        如果iframe与父窗口也有同源策略的限制,父域无法直接读取不同源的iframe的DOM内容以及监听事件,但是iframe可以调用父窗口提供的api。iframe通过window.parent得到父窗口的window对象,然后父窗口定义一个全局对象供iframe调用。

        例如在页面通过iframe的方式嵌入一个youtobe的视频,如果需要手动播放视频、监听iframe的播放事件,页面需要引入youtobe的视频播放控制api,在这个js文件里面定义了一个全局对象YT:

if (!window['YT']) {var YT = {loading: 0,loaded: 0};}

而在视频iframe的脚本里通过window.parent获取得到父窗口即自己网站的页面:

sr = new Cq(window.parent, d, b)

自已网站的页面也是在这个YT对象自定义一些东西,如添加播放事件监听:

new YT.Player('video', { events:{ 'onStateChange': function(data){... } } });

6. window.postMessage

在上面第(5)点,父窗口无法向不同源的iframe传递东西,通过window.postMessage可以做到,父窗口向iframe传递一个消息,而iframe监听消息事件。

例如在8000端口的页面嵌入了一个9000端口的iframe:

然后9000端口post一个message:

window.onload = function(){
            window.frames[0].postMessage("hello, this is from http://localhost:8000/", "http://server.com:9000/");
        }

postMessage执行的上下文必须是接收信息的window,传递两个参数,第一个是数据,第二个是目标窗口。

同时,iframe即9000端口的页面监听message事件:

  window.addEventListener("message", receiveMessage);

    function receiveMessage(event){
        var origin = event.origin || event.originalEvent.origin; 
        //身份验证
        if (origin !== "http://localhost:8000"){
              return;
        }
        console.log("receiveMessage: " + event.data); 
    }

这样子iframe就可收到父窗口的信息了:

同理iframe也可以向父窗口发送消息:

window.parent.postMessage("hello, this is from http://server.com:9000", "http://localhost:8000");

父窗口收到:

window.postMessage也适用于通过window.open打开的子窗口,方法类似。

补充一点,如果iframe与父窗口是同源的,则父窗口可以直接获取到iframe的内容,这个方法常用于无刷新上传文件。

7. 使用代理避开跨域请求

例如www.a.com/index.html页面去调用www.b.com/service.jsp,可以通过写一个接口www.a.com/service.jsp,由这个接口在后端去调用www.b.com/service.jsp并取到返回值,然后再返回给index.html。

 


参考链接:

1. 什么是跨域请求以及实现跨域的方案

2. Access-Control-Allow- 设置 跨域资源共享 CORS 详解

3. HTTP访问控制(CORS)

4. 同源策略和跨域请求研究

5. Jsonp解决跨域的原理及过程

 

你可能感兴趣的:(HTML笔记,PHP笔记)