CORS
说到CORS,相信前端儿都不陌生,这里我就不多说了,具体可以看看这篇文章。
CORS,主要就是配置Response响应头中的 Access-Control-Allow-Origin 属性为你允许该接口访问的域名。最常见的设置是:
res.header('Access-Control-Allow-Origin', '*'); res.header('Access-Control-Allow-Credentials', 'true'); // 允许服务器端发送Cookie数据
然而,这样的设置是最简单粗暴,同时也是最不安全的。它表示该接口允许所有的域名对它进行跨域请求。然而,在一般实际业务中,都希望该接口只允许对某一个或几个网站开放跨域请求权限,而非全部。
那么,聪明的你肯定想着,多域名白名单还不简单吗,写个正则就好啦?再不行,直接配置 Access-Control-Allow-Origin 属性为用逗号分隔的多个域名不就好了吗?
就像下面这样:
res.header('Access-Control-Allow-Origin', '*.666.com'); // 或者如下 res.header('Access-Control-Allow-Origin', 'a.666.com,b.666.com,c.666.com');
很遗憾地告诉你,这样的写法是无效的。在Node.js中,res的响应头Header中的 Access-Control-Allow-Origin 属性不能匹配除 (*) 以外的正则表达式的,域名之间不能也用逗号分隔。也就是说, Access-Control-Allow-Origin 的属性值只允许设置为单个确定域名字符串或者 (*)。
既然我们希望允许的是多个域名,也不愿意使用不安全的 * 通配符,难道就真不能配置多域名白名单的CORS了吗?
多域名白名单的CORS确实是可以实现的。只是有一点曲线救国的味道。
多域名白名单的CORS实现原理
具体原理可以参考cors库的核心代码:
(function () { 'use strict'; var assign = require('object-assign'); var vary = require('vary'); var defaults = { origin: '*', methods: 'GET,HEAD,PUT,PATCH,POST,DELETE', preflightContinue: false, optionsSuccessStatus: 204 }; function isString(s) { return typeof s === 'string' || s instanceof String; } function isOriginAllowed(origin, allowedOrigin) { if (Array.isArray(allowedOrigin)) { for (var i = 0; i < allowedOrigin.length; ++i) { if (isOriginAllowed(origin, allowedOrigin[i])) { return true; } } return false; } else if (isString(allowedOrigin)) { return origin === allowedOrigin; } else if (allowedOrigin instanceof RegExp) { return allowedOrigin.test(origin); } else { return !!allowedOrigin; } } function configureOrigin(options, req) { var requestOrigin = req.headers.origin, headers = [], isAllowed; if (!options.origin || options.origin === '*') { // allow any origin headers.push([{ key: 'Access-Control-Allow-Origin', value: '*' }]); } else if (isString(options.origin)) { // fixed origin headers.push([{ key: 'Access-Control-Allow-Origin', value: options.origin }]); headers.push([{ key: 'Vary', value: 'Origin' }]); } else { isAllowed = isOriginAllowed(requestOrigin, options.origin); // reflect origin headers.push([{ key: 'Access-Control-Allow-Origin', value: isAllowed "htmlcode">// 判断origin是否在域名白名单列表中 function isOriginAllowed(origin, allowedOrigin) { if (_.isArray(allowedOrigin)) { for(let i = 0; i < allowedOrigin.length; i++) { if(isOriginAllowed(origin, allowedOrigin[i])) { return true; } } return false; } else if (_.isString(allowedOrigin)) { return origin === allowedOrigin; } else if (allowedOrigin instanceof RegExp) { return allowedOrigin.test(origin); } else { return !!allowedOrigin; } } const ALLOW_ORIGIN = [ // 域名白名单 '*.233.666.com', 'hello.world.com', 'hello..*.com' ]; app.post('a/b', function (req, res, next) { let reqOrigin = req.headers.origin; // request响应头的origin属性 // 判断请求是否在域名白名单内 if(isOriginAllowed(reqOrigin, ALLOW_ORIGIN)) { // 设置CORS为请求的Origin值 res.header("Access-Control-Allow-Origin", reqOrigin); res.header('Access-Control-Allow-Credentials', 'true'); // 你的业务代码逻辑代码 ... // ... } else { res.send({ code: -2, msg: '非法请求' }); } });Oh yeah,简直完美~
总结
以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作能带来一定的帮助,如果有疑问大家可以留言交流,谢谢大家对的支持。