什么是 CORS(跨源资源共享)?
CORS(Cross-Origin Resource Sharing)是一种机制,容许网页从不同的域拜访服务器上的资源。
在同源策略下,浏览器限度了跨域拜访,CORS 容许服务器指定哪些源能够拜访其资源。
同源策略 (Same-origin policy)
同源策略在 web 利用平安模型中是一个重要的概念。在这个策略下,浏览器容许第一个网页中蕴含的脚本能够获取第二个网页的数据,前提是这两个网页在同一个源下。
同源:须要 URI、主机名、端口都雷同。
这个策略能够避免一个网页上的歹意脚本通过 DOM 获取其余网页的敏感数据。
须要牢记的一点就是同源策略只利用于脚本,这意味着像 images、css 和其余动静加载的脚本 能够通过对应的标签跨域拜访资源。
是否同源的规定
同源须要满足雷同的协定(scheme),雷同的主机名(host),雷同的端口号(port)
Compared URL | Outcome Reason |
---|---|
http://www.example.com/dir/page2.html | Success Same scheme, host and port |
http://www.example.com/dir2/other.html | Success Same scheme, host and port |
http://username:password@www.example.com/dir2/other.html | Success Same scheme, host and port |
http://www.example.com:81/dir/other.html | Failure Same scheme and host but different port |
https://www.example.com/dir/other.html | Failure Different scheme |
http://en.example.com/dir/other.html | Failure Different host |
http://example.com/dir/other.html | Failure Different host (exact match required) |
http://v2.www.example.com/dir/other.html | Failure Different host (exact match required) |
http://www.example.com:80/dir/other.html | Depends Port explicit. Depends on implementation in browser. |
::: tip
scheme: http https
:::
CORS 存在的意义
跨域资源共享 (CORS) 是一种机制,它应用额定的 HTTP 头来通知浏览器 让运行在一个 origin (domain) 上的 Web 利用被准许拜访来自不同源服务器上的指定的资源。
出于安全性,浏览器限度脚本内发动的跨源 HTTP 申请。例如,XMLHttpRequest 和 Fetch API 遵循同源策略。这意味着应用这些 API 的 Web 应用程序只能从加载应用程序的同一个域申请 HTTP 资源,除非响应报文蕴含了正确 CORS 响应头。
跨源域资源共享(CORS)机制容许 Web 应用服务器进行跨源访问控制,从而使跨源数据传输得以平安进行。
CORS 的工作原理是什么?
当浏览器发动跨域申请时,会在申请头中增加 Origin 字段,批示申请的源。服务器接管到申请后,会在响应头中增加 Access-Control-Allow-Origin 字段,批示容许拜访的源。如果服务器容许该源拜访资源,浏览器会将响应返回给客户端。
CORS 中的预检申请是什么?为什么须要预检申请?
预检申请是浏览器在发送跨域申请前发送的一种 OPTIONS 申请,用于查看服务器是否反对跨域申请。预检申请中蕴含一些额定的头信息,如 Access-Control-Request-Method、Access-Control-Request-Headers 等。
预检申请的目标是确保服务器反对跨域申请,防止跨域申请对服务器造成平安危险。只有在服务器返回容许的响应头后,浏览器才会发送理论的跨域申请。
理解了下面的内容,咱们解决浏览器控制台的跨域问题,个别有两个方向:
- 后端服务设置容许跨域拜访
- 前端通过代理拜访资源 (开发阶段应用)
如何在服务器端配置 CORS?
在服务器端配置 CORS 通常须要在响应头中增加一些字段,如 Access-Control-Allow-Origin、Access-Control-Allow-Methods、Access-Control-Allow-Headers 等。通过配置这些字段,能够管制容许的源、申请办法和申请头。
用 Node.js 的一个框架 koa 来举例,解决跨域应用 koa-cors 非常简单,如下:
var koa = require('koa');
var route = require('koa-route');
var cors = require('koa-cors');
var app = koa();
app.use(cors());
app.use(route.get('/', function() {this.body = { msg: 'Hello World!'};
}));
app.listen(3000);
这个中间件大略做了这样的事件:
module.exports = () => {return async function(ctx, next) {ctx.set('Content-Type', 'application/json');
ctx.set('Access-Control-Allow-Origin', '*');
ctx.set('Access-Control-Allow-Methods', 'GET, POST, PATCH, DELETE, PUT');
ctx.set('Access-Control-Allow-Headers', 'X-Requested-With, content-type, X-Authorization, X-uuid');
ctx.json = json.bind(ctx);
ctx.halt = halt.bind(ctx);
try {await next();
} catch (e) {return ctx.halt(e.code, e.message);
}
};
};
这样前端收到的响应会是上面的样子:
HTTP/1.1 200 OK
Date: Mon, 01 Dec 2008 00:23:53 GMT
Server: Apache/2
Access-Control-Allow-Origin: *
Keep-Alive: timeout=2, max=100
Connection: Keep-Alive
Transfer-Encoding: chunked
Content-Type: application/xml
本例中,服务端返回的 Access-Control-Allow-Origin: * 表明,该资源能够被 任意 外域拜访。
前端代理
如果应用了 webpack 那么配置一个代理就很容易,通过代理模拟出和服务端同源的申请。
//webpack.config.js
module.exports = {
//...
devServer: {
proxy: {
'/api': {
target: 'http://localhost:3000',
pathRewrite: {'^/api': ''},
},
},
},
};
这样前端发动的申请蕴含 /api 的门路就会被代理到 http://localhost:3000,并且会把 /api 替换为空。如果你的接口地址原本就包含 /api,那只有把 pathRewrite: {‘^/api’: ”} 去掉即可。
这个 devServer 代理应用功能强大的 http-proxy-middleware 软件包。
http-proxy-middleware 外部又应用了 node-http-proxy
服务端代理
服务端代理是一种解决跨域拜访的办法,通过在服务端发动申请并将后果返回给客户端,绕过了浏览器的同源策略限度。通常能够应用 Node.js、Java、Python 等后端语言来实现服务端代理。
以下是一个应用 Node.js 实现服务端代理的示例代码:
const express = require('express');
const request = require('request');
const app = express();
app.get('/proxy', (req, res) => {
const url = req.query.url;
request(url, (error, response, body) => {if (!error && response.statusCode === 200) {res.send(body);
} else {res.status(500).send('Error');
}
});
});
app.listen(3000, () => {console.log('Server is running on port 3000');
});
在下面的示例中,当客户端发送申请到 /proxy 接口时,服务端会将申请转发到指定的 URL,并将后果返回给客户端。
总结
总的来说,跨域资源共享是一个常见的 Web 开发问题,理解跨域资源共享的原理和解决办法对于开发安全可靠的 Web 应用程序十分重要。
参考链接
跨源资源共享(CORS)