什么是跨域?
同源策略(Same-origin policy)
同源策略在web应用安全模型中是一个重要的概念。在这个策略下,浏览器允许第一个网页中包含的脚本可以获取第二个网页的数据,前提是这两个网页在同一个源下。
同源:需要URI、主机名、端口都相同。
这个策略可以防止一个网页上的恶意脚本通过DOM获取其他网页的敏感数据。
需要牢记的一点就是同源策略只应用于脚本,这意味着像images、css和其他动态加载的脚本 可以通过对应的标签跨域访问资源。
CORS
跨域资源共享 Cross-origin resource sharing (CORS) 是一种机制,它使用额外的 HTTP 头来告诉浏览器 让运行在一个 origin (domain) 上的Web应用被准许访问来自不同源服务器上的指定的资源。
CORS存在的意义
出于安全性,浏览器限制脚本内发起的跨源HTTP请求。 例如,XMLHttpRequest 和 Fetch API 遵循同源策略。这意味着使用这些 API 的 Web 应用程序只能从加载应用程序的同一个域请求 HTTP 资源,除非响应报文包含了正确 CORS 响应头。
跨源域资源共享(CORS)机制允许 Web 应用服务器进行跨源访问控制,从而使跨源数据传输得以安全进行。
了解了上面的内容,我们解决浏览器控制台的跨域问题,一般有两个方向:
- 后端服务设置允许跨域访问
- 前端通过代理访问资源
服务端
用 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': '' }去掉即可。
更多高级功能可参考 官网
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。