携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第13天,点击查看活动详情
CORS(Cross-Origin Resource Sharing,跨域资源共享)主要是定义了当我们必须要访问跨域资源的时候,浏览器与服务器应该如何进行沟通。CORS背后的基本思想,主要就是使用自定义的HTTP头部让浏览器与服务器进行沟通,从而决定请求或响应是应该成功,还是失败。下面我们来看两种请求的跨域实现:
简单请求的跨域实现:
我们所说的简单请求就是满足下面两个条件的请求:
- 请求方法是HEAD、GET、POST三种方法之一
- HTTP的头信息不超出以下几种字段:
- Accept
- Accept-Language
- Content-Language
- Last-Event-ID
- Content-Type:其中Content-Type只限于后面三个值application/x-www-form-urlencoded、multipart/form-data、text/plain
符合上述两个条件的请求,均为简单请求。当发送简单请求时,服务端只需要增加一个Origin头部(Access-Control-Allow-Origin),就可以开启CORS。
Access-Control-Allow-Origin这个属性表示有哪些域名可以访问该资源,如果该属性设置成通配符则表示所有域名都可以访问该资源。如果没有这个头部,或有这个头部但来源信息不匹配,那么浏览器就会驳回请求。
let whitList = ['http://localhost:3000']
app.use(function (req,res,next) {
let origin = req.headers.origin;
if(whitList.includes(origin)){
// 设置哪个源可以访问我
res.setHeader('Access-Control-Allow-Origin', origin);
}
next();
});
上述例子中,我们将可以访问的域名加入一个白名单列表,然后判断如果访问源在白名单里,则将Access-Control-Allow-Origin的值设置成该访问源,这样就不会跨域了。
复杂请求的跨域实现
除了上述的简单请求以外,其余的均为复杂请求。复杂请求在CORS请求的时候,会增加一次预检请求(options请求),通过options请求就可以知道服务端是否允许我们跨域。发送复杂请求的时候,服务端一般会设置以下几种头部信息:
- Access-Control-Allow-Origin: 与简单请求相同
- Access-Control-Allow-Methods: 允许的方法
- Access-Control-Allow-Headers: 允许的头部
- Access-Control-Max-Age: 预检请求的存活时间
- Access-Control-Allow-Credentials: true
在默认情况下,跨源请求不会提供凭据(cookie、HTTP认证等),我们通过将withCredentials属性设置为true,可以指定某个请求发送凭据,这时候服务器接收带凭据的请求,会设置Access-Control-Allow-Credentials: true这个http头部信息来进行响应。
下面我们来看一个复杂请求的设置例子:
app.use(function (req,res,next) {
let origin = ‘http://localhost:3000’;
res.setHeader('Access-Control-Allow-Origin', origin);
res.setHeader('Access-Control-Allow-Headers','name');
res.setHeader('Access-Control-Allow-Methods','PUT');
res.setHeader('Access-Control-Max-Age',6);
res.setHeader('Access-Control-Allow-Credentials', true);
if(req.method === 'OPTIONS'){
res.end();
}
next();
});
上述的例子中,服务端设置了可以访问的源localhost:3000,访问时可以携带的头name,请求方法put,预检请求的时间以及允许凭证这些选项。在我们前端(localhost:3000下)发送请求时,使用put方法进行调用,设置withCredentials为true即可携带cookie凭证,然后也可以设置请求头name,这样基本就实现了复杂请求的跨域。