前端学习笔记【跨域与浏览器的同源策略】

208 阅读3分钟

跨域(由浏览器同源策略限制的一类请求场景)

定义

当一个请求url的协议域名端口三者之间任意一个与当前页面url不同即为跨域

同源策略限制以下几种行为:

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

解决方法:

1. 通过JSONP(jsonp缺点:只能实现get一种请求)

比如下面的例子利用script标签加回调函数

可以在

    <script>
        function f(data){
    		alert(data)
    	}
    </script>
    <script src="http://localhost:8000?callback=f"></script>
    var app2 = express();
    app2.get("/",function(req,res){
    	var funcname = req.query.callback;
        res.send(funcname+"('messgae')")
    })
    app2.listen(8000)

2. 跨域资源共享(CORS)

浏览器将CORS请求分成两类:简单请求(simple request)和非简单请求(not-so-simple request)。

简单请求

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

(1) 请求方法是以下三种方法之一:

  • HEAD
  • GET
  • POST

(2)HTTP的头信息不超出以下几种字段:

  • Accept
  • Accept-Language
  • Content-Language
  • Last-Event-ID
  • Content-Type:只限于三个值
    • application/x-www-form-urlencoded、中默认的encType,form表单数据被编码为key/value格式发送到服务器(表单默认的提交数据的格式)
    • multipart/form-data、需要在表单中进行文件上传时,就需要使用该格式
    • text/plain 纯文本格式

对于简单请求,浏览器直接发出CORS请求。具体来说,就是在头信息之中,增加一个Origin字段

Origin字段用来说明,本次请求来自哪个源(协议 + 域名 + 端口)。服务器根据这个值,决定是否同意这次请求。

如果Origin指定的域名在许可范围内,服务器返回的响应,会多出几个头信息字段。

    //该字段是必须的。它的值要么是请求时Origin字段的值,要么是一个*,表示接受任意域名的请求。
    Access-Control-Allow-Origin: http://api.bob.com
    Access-Control-Allow-Credentials: true
    Access-Control-Expose-Headers: FooBar
    Content-Type: text/html; charset=utf-8

CORS请求默认不发送Cookie和HTTP认证信息。如果要把Cookie发到服务器,一方面要服务器同意,指定Access-Control-Allow-Credentials字段。

Access-Control-Allow-Credentials: true

另一方面,开发者必须在AJAX请求中打开withCredentials属性。

var xhr = new XMLHttpRequest();
xhr.withCredentials = true;

下面是一个修改案例

    //比如在express后端  直接修改响应头!!!
    var app2 = express();
    app2.get("/",function(req,res){
    	res.header("Access-Control-Allow-Origin","*")
    	res.send("message")
    })
    app2.listen(8000)

非简单请求

非简单请求是那种对服务器有特殊要求的请求,比如请求方法是PUTDELETE,或者Content-Type字段的类型是application/json

非简单请求的CORS请求,会在正式通信之前,增加一次HTTP查询请求,称为"预检"请求(preflight)。

浏览器先询问服务器,当前网页所在的域名是否在服务器的许可名单之中,以及可以使用哪些HTTP动词和头信息字段。只有得到肯定答复,浏览器才会发出正式的XMLHttpRequest请求,否则就报错。

CORS与JSONP的使用目的相同,但是比JSONP更强大。

推荐视频:

www.bilibili.com/video/BV1Kt…

参考文献:

阮一峰 跨域资源共享 CORS 详解

其他解决跨域方法:

  • document.domain + iframe跨域
  • location.hash + iframe
  • window.name + iframe跨域
  • postMessage跨域
  • nginx代理跨域
  • nodejs中间件代理跨域
  • WebSocket协议跨域

见相关文章: segmentfault.com/a/119000001…

后期再补

其他阅读学习[ajax,fetch,axios]

ajax

    $.ajax({
      url: "test.html",
      context: document.body
    }).done(function() {
      $( this ).addClass( "done" );
    });

文章推荐:

api.jquery.com/jquery.ajax…

fetch

    //使用案例 提交表单
    const form = document.querySelector('form');
    
    const response = await fetch('/users', {
      method: 'POST',
      body: new FormData(form)
    })

文章推荐:

阮一峰 Fetch API教程

axios

    //使用案例 发送 POST 请求
    axios({
      method: 'post',
      url: '/user/12345',
      headers:{'content-type':"application/x-www-form-urlencoded"},
      data: {
        firstName: 'Fred',
        lastName: 'Flintstone'
      }
    }).then(res=>{console.log(res.data)});

文章推荐:

使用说明 · Axios 中文说明

axios中文网

推荐视频:

www.bilibili.com/video/BV14t…