国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 語言 > JavaScript > 正文

Node.js設置CORS跨域請求中多域名白名單的方法

2024-05-06 15:19:18
字體:
供稿:網(wǎng)友

CORS

說到CORS,相信前端兒都不陌生,這里我就不多說了,具體可以看看這篇文章。

CORS,主要就是配置Response響應頭中的 Access-Control-Allow-Origin 屬性為你允許該接口訪問的域名。最常見的設置是:

res.header('Access-Control-Allow-Origin', '*');res.header('Access-Control-Allow-Credentials', 'true'); // 允許服務器端發(fā)送Cookie數(shù)據(jù)

然而,這樣的設置是最簡單粗暴,同時也是最不安全的。它表示該接口允許所有的域名對它進行跨域請求。然而,在一般實際業(yè)務中,都希望該接口只允許對某一個或幾個網(wǎng)站開放跨域請求權(quán)限,而非全部。

那么,聰明的你肯定想著,多域名白名單還不簡單嗎,寫個正則就好啦?再不行,直接配置 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確實是可以實現(xiàn)的。只是有一點曲線救國的味道。

多域名白名單的CORS實現(xiàn)原理

具體原理可以參考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: 'true' }; } 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't 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;}());            
發(fā)表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發(fā)表

圖片精選

主站蜘蛛池模板: 报价| 武强县| 延吉市| 察雅县| 玉溪市| 海宁市| 望都县| 新河县| 赤峰市| 宁明县| 阿拉善左旗| 永济市| 天门市| 白沙| 黔东| 汉沽区| 民丰县| 明星| 长葛市| 高安市| 娄烦县| 竹山县| 安顺市| 天长市| 朝阳市| 沾化县| 耿马| 武清区| 通辽市| 辽宁省| 鹿泉市| 平原县| 平远县| 科技| 中卫市| 师宗县| 汪清县| 云安县| 佳木斯市| 新晃| 永修县|