我的 API 站点现在给我的几个工具站提供着接口服务,其中就包括了趣优选戏词等。由于域名不同,跨域是一开始就会遇到的问题。如何设置以允许不同域名的站点的跨域请求,我找到了一个方案。

先前的方式非常简单粗暴,直接设置 Access-Control-Allow-Origin: *。没有判断任何的请求来源,都是允许请求。带来的好处就是调试的时候方便,但是弊端也显而易见:容易被恶意调用。

因为一开始的接口是为趣优选提供的,这部分接口返回的跳转链接其实是有关联到我的一些账号上的,所以想着如果这部分被人调用收益的还是我,于是就没有想着做请求限制。

但最近开始着手在做戏词网页版的小程序扫码登录,请求白名单也是势在必行了。具体做法是这样的:

把原来的代码:

1
2
3
app.all('*', function(req, res, next) {
res.header("Access-Control-Allow-Origin", '*');
}

改为

1
2
3
4
5
6
7
8
9
10
11
12
app.all("*", function(req, res, next) {
let whiteList = [
"http://example.site1",
"http://example.site2",
"..."
];
if (whiteList.indexOf(req.headers.origin) > -1) {
res.header("Access-Control-Allow-Origin", req.headers.origin);
}else{
res.sendStatus(406); // Not Acceptable
}
}

通过手动设置白名单的方式,配置好我的几个工具站的域名地址。在请求的时候判断当前请求来源是否在白名单内。如果是的话,则允许跨域访问,设置头部为当前来源;否则返回一个失败的状态码,请求结束。这边我选用的是 406: Not Accepetable。可以根绝自己的需要配置相对应的 HTTP 状态码。

后续可改进的地方

本着又不是不能用的思想方针,这个版本就先这样了。但是也想了后续能有哪些地方可以优化。

比如,现在只判断来源,没有判断是要访问哪个接口。来自 A 站点的请求可能需要做跨域限制,来自 B 站点的又想要全站开放。这个有优化的空间的。

再比如,现在的白名单是手工配置的,后面可能由配置文件提供,或者其他方式提供。不过现在运行的项目不多,层次也不复杂。就不搞这么麻烦的了。

以上。