什么是同源策略及限制
如果两个uri的协议, 域名, 端口三者完全相同,就称之为同源。
同源策略限制从一个源加载的文档或脚本如何与来自另一个源的资源进行交互
这是一个用于隔离潜在恶意文件的关键安全机制:
- cookie,localstorage,indexdb无法读取
- dom无法获得
- ajax请求不能发送
跨域通信的几种方式
- JSONP: callback后面的参数是函数,返回的字段是函数的参数,原理src的元素不会被同源策略拦截(img, link, script这些元素)
1 2 3 4 5 6
|
<script> const add = (a, b) => { console.log('a and b', a, b, a + b)} </script> <script src="http://localhost:2000/api/todo/all/jsonp?callback=add¶m1=10¶m2=20" />
|
1 2 3 4 5 6
| app.get('/api/todo/all/jsonp', (request, response) => { let query = { reqeust } let {callback, param1, param2} = { query } let s = `${callback}(${param1}, ${param2})` response.send(s) })
|
1 2 3 4 5 6
| let b = document.querySelector('iframe') b.src = b.src + '#' + 'json.stringify(data)' window.onhashchange = function() { let data = window.location.hash }
|
1 2 3 4 5 6
| Bwindow.postMessage('data', 'http://B.com') Awindow.addEventListener('message', function(event){ log(event.origin) log(event.source) log(event.data) })
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| var ws = new WebSocket('wss://localhost:8080');
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."); };
|
1 2 3 4 5 6 7
| const Koa = require('koa') const cors = require('@koa/cors')
const app = new Koa() app.use(cors({ origin: '*' }))
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| server { listen 9000; server_name localhost;
access_log /var/log/nginx/host.access.log main; error_log /var/log/nginx/error.log error;
location / { root /usr/share/nginx/html; index index.html index.html; }
location /api/ { rewrite /api/(.*) /$1 break; proxy_pass http://49.234.21.254:8562; }
error_page 500 502 503 504 /50x.html; location = /50x.html { root /usr/share/nginx/html; } }
|
在跨域通讯的CORS方式中浏览器做了什么处理
浏览器将CORS请求分成两类:简单请求(simple request)和非简单请求(not-so-simple request) 然后它会给请求报文和响应报文的头部添加一些字段
简单请求, 同时满足以下两大条件
请求方法是以下三种方法之一
HTTP的头信息不超出以下几种字段
简单请求的相关头部字段
1
| Origin: http://api.bob.com
|
1 2 3 4 5 6 7
| Access-Control-Allow-Origin: http://api.bob.com # 表示是否允许发送Cookie Access-Control-Allow-Credentials: true # XMLHttpRequest对象的getResponseHeader()方法只能拿到6个基本字段: # Cache-Control、Content-Language、Content-Type、Expires、Last-Modified、Pragma。 # 如果想拿到其他字段,就必须在Access-Control-Expose-Headers里面指定 Access-Control-Expose-Headers: FooBar
|
非简单请求的相关头部字段
非简单请求是那种对服务器有特殊要求的请求,比如请求方法是PUT
或DELETE
,或者Content-Type
字段的类型是application/json
。
非简单请求的CORS请求,会在正式通信之前,增加一次HTTP查询请求,称为”预检”请求
关于预检请求:
浏览器先询问服务器,当前网页所在的域名是否在服务器的许可名单之中,以及可以使用哪些HTTP动词和头信息字段。只有得到肯定答复,浏览器才会发出正式的XMLHttpRequest
请求,否则就报错。
预检请求的相关字段
1 2 3 4
| Origin: http://api.bob.com Access-Control-Request-Method: PUT # 指定浏览器CORS请求会额外发送的头信息字段 Access-Control-Request-Headers: X-Custom-Header
|
1 2 3 4 5
| Access-Control-Allow-Origin: http://api.bob.com # 表明服务器支持的所有跨域请求的方法 Access-Control-Allow-Methods: GET, POST, PUT # 表明服务器支持的所有头信息字段,不限于浏览器在"预检"中请求的字段 Access-Control-Allow-Headers: X-Custom-Header
|