1200字范文,内容丰富有趣,写作的好帮手!
1200字范文 > Node.js设置CORS跨域请求中多域名白名单的示例代码分享

Node.js设置CORS跨域请求中多域名白名单的示例代码分享

时间:2023-11-27 03:59:00

相关推荐

Node.js设置CORS跨域请求中多域名白名单的示例代码分享

web前端|js教程

Node.js,CORS,多域名白名单

web前端-js教程

这篇文章主要介绍了Node.js设置CORS跨域请求中多域名白名单的方法,文中通过示例代码介绍的非常详细,相信对大家具有一定的参考价值,需要的朋友们下面来一起看看吧。

在线购买支付源码,vscode 怎么设置插件,大华 sdk ubuntu,tomcat调优书籍,sqlite的一般用法,身上有透明小爬虫像小蜘蛛,php 面向对象思想,花都seo网络营销,php网站上传教程,中国酒店网页模板免费下载lzw

CORS

wp08影视源码,ubuntu复制代码命令,爬虫前后端交互,php占位,仿站 seolzw

说到CORS,相信前端儿都不陌生,这里我就不多说了,具体可以看看这篇文章。

菠菜站源码,vscode设置关键字,ubuntu wifi标志,tomcat改为服务启动,长形黑色爬虫,服务器php升级,玉溪谷歌seo营销公司,网站栏目设置说明,destoon绿色苗木网站模板lzw

CORS,主要就是配置Response响应头中的 Access-Control-Allow-Origin 属性为你允许该接口访问的域名。最常见的设置是:

res.header(Access-Control-Allow-Origin, *);res.header(Access-Control-Allow-Credentials, rue); // 允许服务器端发送Cookie数据

然而,这样的设置是最简单粗暴,同时也是最不安全的。它表示该接口允许所有的域名对它进行跨域请求。然而,在一般实际业务中,都希望该接口只允许对某一个或几个网站开放跨域请求权限,而非全部。

那么,聪明的你肯定想着,多域名白名单还不简单吗,写个正则就好啦?再不行,直接配置 Access-Control-Allow-Origin 属性为用逗号分隔的多个域名不就好了吗?

就像下面这样:

res.header(Access-Control-Allow-Origin, *.); // 或者如下res.header(Access-Control-Allow-Origin, ,,);

很遗憾地告诉你,这样的写法是无效的。在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 ? requestOrigin : false }]); headers.push([{ key: Vary, value: Origin }]); } return headers; } function configureMethods(options) { var methods = options.methods; if (methods.join) { methods = options.methods.join(,); // .methods is an array, so turn it into a string } return { key: Access-Control-Allow-Methods, value: methods }; } function configureCredentials(options) { if (options.credentials === true) { return { key: Access-Control-Allow-Credentials, value: rue }; } return null; } function configureAllowedHeaders(options, req) { var allowedHeaders = options.allowedHeaders || options.headers; var headers = []; if (!allowedHeaders) { allowedHeaders = req.headers[access-control-request-headers]; // .headers wasn specified, so reflect the request headers headers.push([{ key: Vary, value: Access-Control-Request-Headers }]); } else if (allowedHeaders.join) { allowedHeaders = allowedHeaders.join(,); // .headers is an array, so turn it into a string } if (allowedHeaders && allowedHeaders.length) { headers.push([{ key: Access-Control-Allow-Headers, value: allowedHeaders }]); } return headers; } function configureExposedHeaders(options) { var headers = options.exposedHeaders; if (!headers) { return null; } else if (headers.join) { headers = headers.join(,); // .headers is an array, so turn it into a string } if (headers && headers.length) { return { key: Access-Control-Expose-Headers, value: headers }; } return null; } function configureMaxAge(options) { var maxAge = options.maxAge && options.maxAge.toString(); if (maxAge && maxAge.length) { return { key: Access-Control-Max-Age, value: maxAge }; } return null; } function applyHeaders(headers, res) { for (var i = 0, n = headers.length; i < n; i++) { var header = headers[i]; if (header) { if (Array.isArray(header)) { applyHeaders(header, res); } else if (header.key === Vary && header.value) { vary(res, header.value); } else if (header.value) { res.setHeader(header.key, header.value); } } } } function cors(options, req, res, next) { var headers = [], method = req.method && req.method.toUpperCase && req.method.toUpperCase(); if (method === OPTIONS) { // preflight headers.push(configureOrigin(options, req)); headers.push(configureCredentials(options, req)); headers.push(configureMethods(options, req)); headers.push(configureAllowedHeaders(options, req)); headers.push(configureMaxAge(options, req)); headers.push(configureExposedHeaders(options, req)); applyHeaders(headers, res); if (options.preflightContinue ) { next(); } else { res.statusCode = options.optionsSuccessStatus || defaults.optionsSuccessStatus; res.end(); } } else { // actual response headers.push(configureOrigin(options, req)); headers.push(configureCredentials(options, req)); headers.push(configureExposedHeaders(options, req)); applyHeaders(headers, res); next(); } } function middlewareWrapper(o) { if (typeof o !== function) { o = assign({}, defaults, o); } // if options are static (either via defaults or custom options passed in), wrap in a function var optionsCallback = null; if (typeof o === function) { optionsCallback = o; } else { optionsCallback = function (req, cb) { cb(null, o); }; } return function corsMiddleware(req, res, next) { optionsCallback(req, function (err, options) { if (err) { next(err); } else { var originCallback = null; if (options.origin && typeof options.origin === function) { originCallback = options.origin; } else if (options.origin) { originCallback = function (origin, cb) { cb(null, options.origin); }; } if (originCallback) { originCallback(req.headers.origin, function (err2, origin) { if (err2 || !origin) { next(err2); } else { var corsOptions = Object.create(options); corsOptions.origin = origin; cors(corsOptions, req, res, next); } }); } else { next(); } } }); }; } // can pass either an options hash, an options delegate, or nothing module.exports = middlewareWrapper;}());

实现原理是这样的:

既然 Access-Control-Allow-Origin 属性已经明确不能设置多个域名,那么我们只得放弃这条路了。

最流行也是最有效的方法就是,在服务器端判断请求的Header中Origin属性值(req.header.origin)是否在我们的域名白名单列表内。如果在白名单列表内,那么我们就把 Access-Control-Allow-Origin 设置成当前的Origin值,这样就满足了Access-Control-Allow-Origin 的单一域名要求,也能确保当前请求通过访问;如果不在白名单列表内,则返回错误信息。

这样,我们就把跨域请求的验证,从浏览器端转移到服务端来了。对Origin字符串的验证就变成了相当于常规字符串的验证,我们不仅可以使用数组列表验证,还可以使用正则匹配。

具体代码如下:

// 判断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 = [ // 域名白名单 *., \, 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, rue); // 你的业务代码逻辑代码 ... // ... } else { res.send({ code: -2, msg: 非法请求 }); }});

Oh yeah,简直完美~

总结

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。