찾다
웹 프론트엔드JS 튜토리얼CORS 교차 도메인 요청에서 다중 도메인 이름 화이트리스트를 설정하기 위한 Node.js의 샘플 코드 공유

이 글에서는 주로 Node.js CORS 크로스 도메인 요청에서 다중 도메인 이름 화이트리스트를 설정하는 방법을 샘플 코드를 통해 자세히 소개하고 있습니다. 그것은 모든 사람에게 유용할 것이라고 믿습니다. 필요한 친구는 아래를 살펴볼 수 있습니다.

CORS

CORS라고 하면 프론트엔드는 다들 잘 아실 거라 생각해서 여기서는 자세히 설명하지 않겠습니다. 자세한 내용은 이 기사를 읽어보세요.

CORS는 주로 인터페이스 액세스를 허용하는 도메인 이름에 대한 응답 헤더의 Access-Control-Allow-Origin 속성을 구성합니다. 가장 일반적인 설정은

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

입니다. 그러나 이 설정은 가장 단순하고 조야하며 가장 안전하지도 않습니다. 이는 인터페이스가 모든 도메인 이름이 도메인 간 요청을 할 수 있도록 허용한다는 의미입니다. 그러나 일반적인 실제 비즈니스에서는 인터페이스가 전체가 아닌 하나 또는 소수의 웹사이트에만 도메인 간 요청 권한을 허용하는 것으로 예상됩니다.

그래서 똑똑한 분들은 여러 도메인 이름을 화이트리스트에 추가하는 것이 쉽지 않을까요? 그냥 일반적인 규칙만 작성하면 된다고 생각하실 것입니다. 그래도 작동하지 않으면 Access-Control-Allow-Origin 속성을 쉼표로 구분된 여러 도메인 이름에 직접 구성하는 것이 더 좋지 않을까요?

이렇게:

아아아아

이러한 글쓰기 방식은 유효하지 않다는 점을 말씀드리게 되어 죄송합니다. Node.js에서는 res 응답 헤더의 Access-Control-Allow-Origin 속성이 (*) 이외의 정규식과 일치할 수 없으며 도메인 이름을 쉼표로 구분할 수 없습니다. 즉, Access-Control-Allow-Origin의 속성 값은 단일 특정 도메인 이름 문자열 또는 (*)에만 설정되도록 허용됩니다.

여러 도메인 이름을 허용하고 안전하지 않은 * 와일드카드 를 사용하고 싶지 않기 때문에 여러 도메인 이름 화이트리스트에 대해 CORS를 구성할 수 없다는 것이 사실입니까?

여러 도메인 이름 화이트리스트가 있는 CORS는 실제로 달성 가능합니다. 나라를 구하기 위한 약간의 반전이 있을 뿐입니다.

다중 도메인 화이트리스트의 CORS 구현 원칙

구체적인 원칙은 cors 라이브러리의 핵심 코드를 참조하세요.

res.header('Access-Control-Allow-Origin', '*.666.com'); 

// 或者如下
res.header('Access-Control-Allow-Origin', 'a.666.com,b.666.com,c.666.com');

구현 원칙은 다음과 같습니다.

Access-Control-Allow-Origin 속성에서 여러 도메인 이름을 설정할 수 없음을 분명히 하였으므로, 우리는 이 길을 포기해야 합니다.

가장 널리 사용되고 효과적인 방법은 요청된 헤더의 Origin 속성 값(req.header.origin)이 도메인 이름 허용 목록에 있는지 서버 측에서 확인하는 것입니다. 화이트리스트에 있는 경우 Access-Control-Allow-Origin을 현재 Origin 값으로 설정합니다. 이는 Access-Control-Allow-Origin의 단일 도메인 이름 요구 사항을 충족하고 현재 요청이 있는 경우 액세스되도록 합니다. 화이트리스트에 없으면 오류 메시지가 반환됩니다.

이런 방식으로 교차 도메인 요청 확인을 브라우저에서 서버로 전송합니다. 원본 문자열 확인은 일반 문자열 확인과 동일하게 됩니다. 배열 목록 확인을 사용할 수 있을 뿐만 아니라 일반 일치도 사용할 수 있습니다.

구체 코드는 다음과 같습니다.

(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 === &#39;*&#39;) {
 // allow any origin
 headers.push([{
 key: &#39;Access-Control-Allow-Origin&#39;,
 value: &#39;*&#39;
 }]);
 } else if (isString(options.origin)) {
 // fixed origin
 headers.push([{
 key: &#39;Access-Control-Allow-Origin&#39;,
 value: options.origin
 }]);
 headers.push([{
 key: &#39;Vary&#39;,
 value: &#39;Origin&#39;
 }]);
 } else {
 isAllowed = isOriginAllowed(requestOrigin, options.origin);
 // reflect origin
 headers.push([{
 key: &#39;Access-Control-Allow-Origin&#39;,
 value: isAllowed ? requestOrigin : false
 }]);
 headers.push([{
 key: &#39;Vary&#39;,
 value: &#39;Origin&#39;
 }]);
 }

 return headers;
 }

 function configureMethods(options) {
 var methods = options.methods;
 if (methods.join) {
 methods = options.methods.join(&#39;,&#39;); // .methods is an array, so turn it into a string
 }
 return {
 key: &#39;Access-Control-Allow-Methods&#39;,
 value: methods
 };
 }

 function configureCredentials(options) {
 if (options.credentials === true) {
 return {
 key: &#39;Access-Control-Allow-Credentials&#39;,
 value: &#39;true&#39;
 };
 }
 return null;
 }

 function configureAllowedHeaders(options, req) {
 var allowedHeaders = options.allowedHeaders || options.headers;
 var headers = [];

 if (!allowedHeaders) {
 allowedHeaders = req.headers[&#39;access-control-request-headers&#39;]; // .headers wasn&#39;t specified, so reflect the request headers
 headers.push([{
 key: &#39;Vary&#39;,
 value: &#39;Access-Control-Request-Headers&#39;
 }]);
 } else if (allowedHeaders.join) {
 allowedHeaders = allowedHeaders.join(&#39;,&#39;); // .headers is an array, so turn it into a string
 }
 if (allowedHeaders && allowedHeaders.length) {
 headers.push([{
 key: &#39;Access-Control-Allow-Headers&#39;,
 value: allowedHeaders
 }]);
 }

 return headers;
 }

 function configureExposedHeaders(options) {
 var headers = options.exposedHeaders;
 if (!headers) {
 return null;
 } else if (headers.join) {
 headers = headers.join(&#39;,&#39;); // .headers is an array, so turn it into a string
 }
 if (headers && headers.length) {
 return {
 key: &#39;Access-Control-Expose-Headers&#39;,
 value: headers
 };
 }
 return null;
 }

 function configureMaxAge(options) {
 var maxAge = options.maxAge && options.maxAge.toString();
 if (maxAge && maxAge.length) {
 return {
 key: &#39;Access-Control-Max-Age&#39;,
 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 === &#39;Vary&#39; && 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 === &#39;OPTIONS&#39;) {
 // 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 !== &#39;function&#39;) {
 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 === &#39;function&#39;) {
 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 === &#39;function&#39;) {
  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;

}());

아 맞네요~

요약

위 내용은 CORS 교차 도메인 요청에서 다중 도메인 이름 화이트리스트를 설정하기 위한 Node.js의 샘플 코드 공유의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
Vercel是什么?怎么部署Node服务?Vercel是什么?怎么部署Node服务?May 07, 2022 pm 09:34 PM

Vercel是什么?本篇文章带大家了解一下Vercel,并介绍一下在Vercel中部署 Node 服务的方法,希望对大家有所帮助!

node.js gm是什么node.js gm是什么Jul 12, 2022 pm 06:28 PM

gm是基于node.js的图片处理插件,它封装了图片处理工具GraphicsMagick(GM)和ImageMagick(IM),可使用spawn的方式调用。gm插件不是node默认安装的,需执行“npm install gm -S”进行安装才可使用。

一文解析package.json和package-lock.json一文解析package.json和package-lock.jsonSep 01, 2022 pm 08:02 PM

本篇文章带大家详解package.json和package-lock.json文件,希望对大家有所帮助!

怎么使用pkg将Node.js项目打包为可执行文件?怎么使用pkg将Node.js项目打包为可执行文件?Jul 26, 2022 pm 07:33 PM

如何用pkg打包nodejs可执行文件?下面本篇文章给大家介绍一下使用pkg将Node.js项目打包为可执行文件的方法,希望对大家有所帮助!

分享一个Nodejs web框架:Fastify分享一个Nodejs web框架:FastifyAug 04, 2022 pm 09:23 PM

本篇文章给大家分享一个Nodejs web框架:Fastify,简单介绍一下Fastify支持的特性、Fastify支持的插件以及Fastify的使用方法,希望对大家有所帮助!

node爬取数据实例:聊聊怎么抓取小说章节node爬取数据实例:聊聊怎么抓取小说章节May 02, 2022 am 10:00 AM

node怎么爬取数据?下面本篇文章给大家分享一个node爬虫实例,聊聊利用node抓取小说章节的方法,希望对大家有所帮助!

手把手带你使用Node.js和adb开发一个手机备份小工具手把手带你使用Node.js和adb开发一个手机备份小工具Apr 14, 2022 pm 09:06 PM

本篇文章给大家分享一个Node实战,介绍一下使用Node.js和adb怎么开发一个手机备份小工具,希望对大家有所帮助!

图文详解node.js如何构建web服务器图文详解node.js如何构建web服务器Aug 08, 2022 am 10:27 AM

先介绍node.js的安装,再介绍使用node.js构建一个简单的web服务器,最后通过一个简单的示例,演示网页与服务器之间的数据交互的实现。

See all articles

핫 AI 도구

Undresser.AI Undress

Undresser.AI Undress

사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover

AI Clothes Remover

사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool

Undress AI Tool

무료로 이미지를 벗다

Clothoff.io

Clothoff.io

AI 옷 제거제

AI Hentai Generator

AI Hentai Generator

AI Hentai를 무료로 생성하십시오.

뜨거운 도구

mPDF

mPDF

mPDF는 UTF-8로 인코딩된 HTML에서 PDF 파일을 생성할 수 있는 PHP 라이브러리입니다. 원저자인 Ian Back은 자신의 웹 사이트에서 "즉시" PDF 파일을 출력하고 다양한 언어를 처리하기 위해 mPDF를 작성했습니다. HTML2FPDF와 같은 원본 스크립트보다 유니코드 글꼴을 사용할 때 속도가 느리고 더 큰 파일을 생성하지만 CSS 스타일 등을 지원하고 많은 개선 사항이 있습니다. RTL(아랍어, 히브리어), CJK(중국어, 일본어, 한국어)를 포함한 거의 모든 언어를 지원합니다. 중첩된 블록 수준 요소(예: P, DIV)를 지원합니다.

SublimeText3 중국어 버전

SublimeText3 중국어 버전

중국어 버전, 사용하기 매우 쉽습니다.

Dreamweaver Mac版

Dreamweaver Mac版

시각적 웹 개발 도구

에디트플러스 중국어 크랙 버전

에디트플러스 중국어 크랙 버전

작은 크기, 구문 강조, 코드 프롬프트 기능을 지원하지 않음

안전한 시험 브라우저

안전한 시험 브라우저

안전한 시험 브라우저는 온라인 시험을 안전하게 치르기 위한 보안 브라우저 환경입니다. 이 소프트웨어는 모든 컴퓨터를 안전한 워크스테이션으로 바꿔줍니다. 이는 모든 유틸리티에 대한 액세스를 제어하고 학생들이 승인되지 않은 리소스를 사용하는 것을 방지합니다.