Development Tip

OPTIONS 경로에 CORS 헤더를 추가하면 브라우저가 내 API에 액세스 할 수없는 이유는 무엇입니까?

yourdevel 2020. 10. 2. 23:23
반응형

OPTIONS 경로에 CORS 헤더를 추가하면 브라우저가 내 API에 액세스 할 수없는 이유는 무엇입니까?


Express.js 웹 프레임 워크를 사용하는 Node.js 애플리케이션에서 CORS를 지원하려고합니다. 나는 읽고 구글 그룹 토론 이 처리하는 방법과 CORS 작품에 대한 몇 가지 기사를 읽는 방법에 대한합니다. 먼저 이렇게했습니다 (코드는 CoffeeScript 구문으로 작성되었습니다).

app.options "*", (req, res) ->
  res.header 'Access-Control-Allow-Origin', '*'
  res.header 'Access-Control-Allow-Credentials', true
  # try: 'POST, GET, PUT, DELETE, OPTIONS'
  res.header 'Access-Control-Allow-Methods', 'GET, OPTIONS'
  # try: 'X-Requested-With, X-HTTP-Method-Override, Content-Type, Accept'
  res.header 'Access-Control-Allow-Headers', 'Content-Type'
  # ...

작동하지 않는 것 같습니다. 내 브라우저 (Chrome)가 초기 OPTIONS 요청을 보내지 않는 것 같습니다. 리소스에 대한 블록을 방금 업데이트했을 때 교차 출처 GET 요청을 다음 주소로 제출해야합니다.

app.get "/somethingelse", (req, res) ->
  # ...
  res.header 'Access-Control-Allow-Origin', '*'
  res.header 'Access-Control-Allow-Credentials', true
  res.header 'Access-Control-Allow-Methods', 'POST, GET, PUT, DELETE, OPTIONS'
  res.header 'Access-Control-Allow-Headers', 'Content-Type'
  # ...

작동합니다 (Chrome에서). 이것은 Safari에서도 작동합니다.

읽었습니다 ...

CORS를 구현하는 브라우저에서 각 교차 출처 GET 또는 POST 요청은 GET 또는 POST가 정상인지 확인하는 OPTIONS 요청이 선행됩니다.

그래서 내 주요 질문은, 내 경우에 이것이 어떻게 발생하지 않는 것 같습니까? 내 app.options 블록이 호출되지 않는 이유는 무엇입니까? 주 app.get 블록에서 헤더를 설정해야하는 이유는 무엇입니까?


주요 질문에 답하기 위해 CORS 사양은 POST 또는 GET에 단순하지 않은 콘텐츠 또는 헤더가있는 경우 POST 또는 GET 앞에 OPTIONS 호출 만 필요합니다.

CORS 사전 요청 (OPTIONS 호출)이 필요한 콘텐츠 유형 은 다음을 제외한 모든 콘텐츠 유형입니다 .

  1. application/x-www-form-urlencoded
  2. multipart/form-data
  3. text/plain

위에 나열된 것 이외의 다른 콘텐츠 유형은 비행 전 요청을 트리거합니다.

헤더의 경우 다음제외한 모든 요청 헤더 가 사전 요청을 트리거합니다.

  1. Accept
  2. Accept-Language
  3. Content-Language
  4. Content-Type
  5. DPR
  6. Save-Data
  7. Viewport-Width
  8. Width

다른 모든 요청 헤더는 비행 전 요청을 트리거합니다.

따라서 다음과 같은 사용자 지정 헤더를 추가 할 수 있습니다. 그러면 x-Trigger: CORS비행 전 요청을 트리거하고 OPTIONS 블록에 도달해야합니다.

참조 MDN 웹 API 참조 - CORS Preflighted 요청


가장 쉬운 방법은 node.js 패키지 cors 를 사용하는 것 입니다. 가장 간단한 사용법은 다음과 같습니다.

var cors = require('cors')

var app = express()
app.use(cors())

물론 필요에 따라 동작을 구성하는 방법에는 여러 가지가 있습니다. 위에 링크 된 페이지는 여러 가지 예를 보여줍니다.


다음 일치하는 경로로 제어권을 넘겨보십시오. Express가 먼저 app.get 경로와 일치하는 경우 다음을 수행하지 않는 한 옵션 경로로 계속 진행되지 않습니다 (Next 사용 참고) .

app.get('somethingelse', function(req, res, next) {
    //..set headers etc.

    next();
});

CORS 항목을 구성하는 측면에서 잘 작동하는 미들웨어에 넣었습니다.

//CORS middleware
var allowCrossDomain = function(req, res, next) {
    res.header('Access-Control-Allow-Origin', 'example.com');
    res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE');
    res.header('Access-Control-Allow-Headers', 'Content-Type');

    next();
}

//...
app.configure(function() {
    app.use(express.bodyParser());
    app.use(express.cookieParser());
    app.use(express.session({ secret: 'cool beans' }));
    app.use(express.methodOverride());
    app.use(allowCrossDomain);
    app.use(app.router);
    app.use(express.static(__dirname + '/public'));
});

동일한 라우팅 아이디어를 유지합니다. 이 코드를 사용합니다.

app.all('/*', function(req, res, next) {
  res.header("Access-Control-Allow-Origin", "*");
  res.header("Access-Control-Allow-Headers", "X-Requested-With");
  next();
});

http://enable-cors.org/server_expressjs.html 예제 와 유사


하다

npm install cors --save

그리고 요청이 진행되는 주 파일에이 줄을 추가하십시오 (어떤 경로보다 먼저 유지).

const cors = require('cors');
const express = require('express');
let app = express();
app.use(cors());
app.options('*', cors());

Express 또는 Connect에 적합한보다 완벽한 미들웨어를 만들었습니다. OPTIONS프리 플라이트 확인 요청을 지원 합니다. CORS가 모든 것에 액세스 할 수 있도록 허용합니다. 액세스를 제한하려면 몇 가지 검사를 할 수 있습니다.

app.use(function(req, res, next) {
    var oneof = false;
    if(req.headers.origin) {
        res.header('Access-Control-Allow-Origin', req.headers.origin);
        oneof = true;
    }
    if(req.headers['access-control-request-method']) {
        res.header('Access-Control-Allow-Methods', req.headers['access-control-request-method']);
        oneof = true;
    }
    if(req.headers['access-control-request-headers']) {
        res.header('Access-Control-Allow-Headers', req.headers['access-control-request-headers']);
        oneof = true;
    }
    if(oneof) {
        res.header('Access-Control-Max-Age', 60 * 60 * 24 * 365);
    }

    // intercept OPTIONS method
    if (oneof && req.method == 'OPTIONS') {
        res.send(200);
    }
    else {
        next();
    }
});

expressjs의 cors 모듈을 설치하십시오. 다음 단계를 따를 수 있습니다>

설치

npm install cors

단순 사용 (모든 CORS 요청 활성화)

var express = require('express');
var cors = require('cors');
var app = express();
app.use(cors());

자세한 내용은 https://github.com/expressjs/cors 로 이동 하십시오.


다음과 같이하십시오.

app.use(function(req, res, next) {
    res.header("Access-Control-Allow-Origin", "*");
    res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
    next();
});

다른 포트에서 실행되는 express + node + ionic으로 테스트가 수행되었습니다.

Localhost:8100

Localhost:5000

// CORS (Cross-Origin Resource Sharing) headers to support Cross-site HTTP requests

app.all('*', function(req, res, next) {
       res.header("Access-Control-Allow-Origin", "*");
       res.header("Access-Control-Allow-Headers", "X-Requested-With");
       res.header('Access-Control-Allow-Headers', 'Content-Type');
       next();
});

먼저 프로젝트에 cors를 설치하기 만하면됩니다. 터미널 (명령 프롬프트)과 cd프로젝트 디렉터리로 이동하여 아래 명령을 실행합니다.

npm install cors --save

그런 다음 server.js 파일을 가져 와서 다음을 추가하도록 코드를 변경합니다.

var cors = require('cors');


var app = express();

app.use(cors());

app.use(function(req, res, next) {
   res.header("Access-Control-Allow-Origin", "*");
   res.header('Access-Control-Allow-Methods', 'DELETE, PUT, GET, POST');
   res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
   next();
});

이거 저 한테 ..


이것은 라우트 내부에서 쉽게 구현할 수 있으므로 meanjs를 사용하고 잘 작동하며 사파리, 크롬 등을 사용합니다.

app.route('/footer-contact-form').post(emailer.sendFooterMail).options(function(req,res,next){ 
        res.header('Access-Control-Allow-Origin', '*'); 
        res.header('Access-Control-Allow-Methods', 'GET, POST');
        res.header('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept');
        return res.send(200);

    });

얼마 전이 문제에 직면하여 nodejs 앱에서 CORS를 허용하기 위해 이렇게했습니다.

먼저 아래 명령을 사용하여 설치해야합니다 cors .

npm install cors --save

이제 ( ) 와 같은 앱 시작 파일에 다음 코드추가하십시오.app.js or server.js

var express = require('express');
var app = express();

var cors = require('cors');
var bodyParser = require('body-parser');

//enables cors
app.use(cors({
  'allowedHeaders': ['sessionId', 'Content-Type'],
  'exposedHeaders': ['sessionId'],
  'origin': '*',
  'methods': 'GET,HEAD,PUT,PATCH,POST,DELETE',
  'preflightContinue': false
}));

require('./router/index')(app);

컨트롤러별로 지정하려면 다음을 사용할 수 있습니다.

res.setHeader('X-Frame-Options', 'ALLOWALL');
res.setHeader('Access-Control-Allow-Origin', '*');
res.setHeader('Access-Control-Allow-Methods', 'POST, GET');
res.setHeader('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept');

이렇게하면 iframe도 허용됩니다.


동일하게 아래 코드를 참조 할 수 있습니다. 출처 : Academind / node-restful-api

const express = require('express');
const app = express();

//acts as a middleware
//to handle CORS Errors
app.use((req, res, next) => { //doesn't send response just adjusts it
    res.header("Access-Control-Allow-Origin", "*") //* to give access to any origin
    res.header(
        "Access-Control-Allow-Headers",
        "Origin, X-Requested-With, Content-Type, Accept, Authorization" //to give access to all the headers provided
    );
    if(req.method === 'OPTIONS'){
        res.header('Access-Control-Allow-Methods', 'PUT, POST, PATCH, DELETE, GET'); //to give access to all the methods provided
        return res.status(200).json({});
    }
    next(); //so that other routes can take over
})

내에서 다음 index.js을 추가했습니다.

app.use((req, res, next) => {
   res.header("Access-Control-Allow-Origin", "*");
   res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
   res.header("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS");
   next();
}) 

Express 4.2.0 (편집 : 4.3.0에서 작동하지 않는 것 같습니다)을 사용한 가장 간단한 솔루션은 다음과 같습니다.

function supportCrossOriginScript(req, res, next) {
    res.status(200);
    res.header("Access-Control-Allow-Origin", "*");
    res.header("Access-Control-Allow-Headers", "Content-Type");

    // res.header("Access-Control-Allow-Headers", "Origin");
    // res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
    // res.header("Access-Control-Allow-Methods","POST, OPTIONS");
    // res.header("Access-Control-Allow-Methods","POST, GET, OPTIONS, DELETE, PUT, HEAD");
    // res.header("Access-Control-Max-Age","1728000");
    next();
}

// Support CORS
app.options('/result', supportCrossOriginScript);

app.post('/result', supportCrossOriginScript, function(req, res) {
    res.send('received');
    // do stuff with req
});

나도 효과가 있다고 생각합니다 app.all('/result', ...)...


Express Middleware를 사용하는 것이 저에게 효과적입니다. 이미 Express를 사용중인 경우 다음 미들웨어 규칙을 추가하기 만하면됩니다. 작동을 시작해야합니다.

app.all("/api/*", function(req, res, next) {
  res.header("Access-Control-Allow-Origin", "*");
  res.header("Access-Control-Allow-Headers", "Cache-Control, Pragma, Origin, Authorization, Content-Type, X-Requested-With");
  res.header("Access-Control-Allow-Methods", "GET, PUT, POST");
  return next();
});

app.all("/api/*", function(req, res, next) {
  if (req.method.toLowerCase() !== "options") {
    return next();
  }
  return res.send(204);
});

참고


npm 요청 패키지 ( https://www.npmjs.com/package/request ) 로이 작업을 수행하는 것이 매우 쉽다는 것을 알았습니다.

그런 다음이 게시물 http://blog.javascripting.com/2015/01/17/dont-hassle-with-cors/ 에 대한 솔루션을 기반으로했습니다.

'use strict'

const express = require('express');
const request = require('request');

let proxyConfig = {
    url : {
        base: 'http://servertoreach.com?id=',
    }
}

/* setting up and configuring node express server for the application */
let server = express();
server.set('port', 3000);


/* methods forwarded to the servertoreach proxy  */
server.use('/somethingElse', function(req, res)
{
    let url = proxyConfig.url.base + req.query.id;
    req.pipe(request(url)).pipe(res);
});


/* start the server */
server.listen(server.get('port'), function() {
    console.log('express server with a proxy listening on port ' + server.get('port'));
});

typescript에서 node.js 패키지 cors 를 사용하려는 경우

/**
* app.ts
* If you use the cors library
*/

import * as express from "express";
[...]
import * as cors from 'cors';

class App {
   public express: express.Application;

   constructor() {
       this.express = express();
       [..]
       this.handleCORSErrors();
   }

   private handleCORSErrors(): any {
       const corsOptions: cors.CorsOptions = {
           origin: 'http://example.com',
           optionsSuccessStatus: 200
       };
       this.express.use(cors(corsOptions));
   }
}

export default new App().express;

cors 오류 처리를 위해 타사 라이브러리를 사용하지 않으려면 handleCORSErrors () 메서드를 변경해야합니다.

/**
* app.ts
* If you do not use the cors library
*/

import * as express from "express";
[...]

class App {
   public express: express.Application;

   constructor() {
       this.express = express();
       [..]
       this.handleCORSErrors();
   }

   private handleCORSErrors(): any {
       this.express.use((req, res, next) => {
           res.header("Access-Control-Allow-Origin", "*");
           res.header(
               "Access-Control-ALlow-Headers",
               "Origin, X-Requested-With, Content-Type, Accept, Authorization"
           );
           if (req.method === "OPTIONS") {
               res.header(
                   "Access-Control-Allow-Methods",
                   "PUT, POST, PATCH, GET, DELETE"
               );
               return res.status(200).json({});
           } 
           next(); // send the request to the next middleware
       });
    }
}

export default new App().express;

app.ts 파일 사용

/**
* server.ts
*/
import * as http from "http";
import app from "./app";

const server: http.Server = http.createServer(app);

const PORT: any = process.env.PORT || 3000;
server.listen(PORT);

이것은 내가 res.sendStatus (200)로 끝내는 차이점을 가진 Pat의 대답과 유사합니다. next () 대신에;

이 코드는 OPTIONS 메소드 유형의 모든 요청을 포착하고 액세스 제어 헤더를 다시 보냅니다.

app.options('/*', (req, res, next) => {
    res.header('Access-Control-Allow-Origin', '*');
    res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE,OPTIONS');
    res.header('Access-Control-Allow-Headers', 'Content-Type, Authorization, Content-Length, X-Requested-With');
    res.sendStatus(200);
});

코드는 질문에서 요청한대로 모든 출처의 CORS를 허용합니다. 그러나 오용을 방지 하려면 *를 특정 출처 (예 : http : // localhost : 8080)바꾸는 것이 좋습니다 .

app.use-method 대신 app.options-method를 사용하므로이 검사를 수행 할 필요가 없습니다.

req.method === 'OPTIONS'

다른 답변에서 볼 수 있습니다.

http://johnzhang.io/options-request-in-express 에서 답을 찾았습니다 .


아래는 나를 위해 일했습니다. 누군가에게 도움이되기를 바랍니다!

const express = require('express');
const cors = require('cors');
let app = express();

app.use(cors({ origin: true }));

https://expressjs.com/en/resources/middleware/cors.html#configuring-cors 에서 참조를 얻었습니다.


CORS를 피하고 대신 다른 서버로 요청을 전달할 수 있습니다.

// config:
var public_folder = __dirname + '/public'
var apiServerHost = 'http://other.server'

// code:
console.log("starting server...");

var express = require('express');
var app = express();
var request = require('request');

// serve static files
app.use(express.static(public_folder));

// if not found, serve from another server
app.use(function(req, res) {
    var url = apiServerHost + req.url;
    req.pipe(request(url)).pipe(res);
});

app.listen(80, function(){
    console.log("server ready");
});

내 웹 앱에 다음 단계를 사용했고 성공했습니다.

익스프레스에 cors 패키지를 추가합니다.

npm install cors --save

bodyParser 구성 뒤에 다음 줄 추가 합니다 . bodyParser 전에 추가하는 데 몇 가지 문제가있었습니다.

 // enable cors to the server
const corsOpt = {
    origin: process.env.CORS_ALLOW_ORIGIN || '*', // this work well to configure origin url in the server
    methods: ['GET', 'PUT', 'POST', 'DELETE', 'OPTIONS'], // to works well with web app, OPTIONS is required
    allowedHeaders: ['Content-Type', 'Authorization'] // allow json and token in the headers
};
app.use(cors(corsOpt)); // cors for all the routes of the application
app.options('*', cors(corsOpt)); // automatic cors gen for HTTP verbs in all routes, This can be redundant but I kept to be sure that will always work.

내가 @OP라면 내 프로그래밍 패러다임을 바꿀 것입니다.

localhost 또는 이와 유사한 요청을하기 때문에 이러한 CORS가 차단되었다고 가정합니다.

궁극적으로 Google Cloud Platform또는 Heroku또는 같은 프로덕션 옵토 인에 배포하려는 경우 원본 허용 또는 프로덕션에서 CORS에 대해 걱정할 필요가 없습니다.

따라서 서버를 테스트 할 때 서버 postman를 배포하고 클라이언트에서 작업 한 후 CORS를 사용 하면 차단되지 않습니다.


Express 미들웨어를 사용하고 도메인 및 방법을 차단할 수 있습니다.

app.use(function(req, res, next) {
  res.header("Access-Control-Allow-Origin", process.env.DOMAIN); // update to match the domain you will make the request from
  res.header("Access-Control-Allow-Methods", "GET,PUT,POST,DELETE");
  res.header(
    "Access-Control-Allow-Headers",
    "Origin, X-Requested-With, Content-Type, Accept"
  );
  next();
});

아래 코드는 작동하지만 먼저 cors를 설치하십시오.

npm 설치-cors 저장

그때:

module.exports = function(app) { 
var express = require("express");
var cors = require('cors');
var router = express.Router();
app.use(cors());

app.post("/movies",cors(), function(req, res) { 
res.send("test");
});

익스프레스 / 외부 라이브러리없이 nodejs를 사용하여 server.js 파일 내에서 아래 방법을 사용했습니다. 여기서 핵심 부분은 요청 헤더에서 오리진을 가져온 다음 서버 응답에서이를 허용하는 것입니다.이 시점에서 일치가 발견되면 허용 된 오리진을 포함하여 반환 될 헤더를 설정할 수 있습니다.

    **const origin = req.headers.origin;**

      let decoder = new StringDecoder('utf-8');
      let buffer = '';
      req.on('data', function (data) {
        buffer += decoder.write(data);
      });
      req.on('end', function () {
        buffer += decoder.end();

        let chosenHandler = typeof (server.router[trimmedPath]) !== 'undefined' ? server.router[trimmedPath] : handlers.notFound;

const data = { ....data object vars}

// should be wrapped in try catch block
      chosenHandler(data, function (statusCode, payload, contentType) {
        server.processHandlerResponse(res, method, trimmedPath, statusCode, payload, contentType, **origin**);


server.processHandlerResponse = function (res, method, trimmedPath, statusCode, payload, contentType, origin) {
  contentType = typeof (contentType) == 'string' ? contentType : 'json';

  statusCode = typeof (statusCode) == 'number' ? statusCode : 200;

  let payloadString = '';
  if (contentType == 'json') {
    res.setHeader('Content-Type', 'application/json');

    const allowedOrigins = ['https://www.domain1.com', 'https://someotherdomain','https://yetanotherdomain',
    ...// as many as you need
  ];
    **if (allowedOrigins.indexOf(origin) > -1) {
        res.setHeader('Access-Control-Allow-Origin', origin);
    }**
    payload = typeof (payload) == 'object' ? payload : {};
    payloadString = JSON.stringify(payload);
  }

... //  if (other content type) ...rinse and repeat..

가장 간단한 방법은 다음을 사용하여 프로젝트에 cors 모듈을 설치하는 것입니다.

npm i --save cors

그런 다음 서버 파일에서 다음을 사용하여 가져옵니다.

import cors from 'cors';

그런 다음 다음과 같이 미들웨어로 사용하십시오.

app.use(cors());

도움이 되었기를 바랍니다!


const express = require("express");
const router = express.Router();
const app = express();
const cors = require("cors"); 



const options = {
  origin: true,
  "Access-Control-Allow-Credentials": true,

  "Access-Control-Allow-Origin": true,
  "Access-Control-Allow-Headers": true,
  "Access-Control-Expose-Headers": true
};


app.use(cors(options));
router.get("/", cors(options), (req, res) => {
  res.render("index", { title: "Express" });
});

module.exports = router;

GOOGLE CHROME의 경우 "Allow-Control-Allow-Origin"확장 프로그램을 추가해야합니다.

Access-Control-Allow-Origin (Response header) 헤더는 Origin 요청 헤더의 값을 반환하여 리소스를 공유 할 수 있는지 여부를 나타냅니다. Access-Control-Allow-Origin 헤더는 교차 출처 액세스를위한 문을 엽니 다.

Access-Control-Allow-Credentials (Response header) : true는 클라이언트가 자격 증명을 사용할 수 있음을 나타내는 데 사용됩니다. 기본적으로 자격 증명 요청에 대한 응답은 클라이언트 스크립트에서 읽을 수 없습니다. 따라서 응답에 액세스 할 수 있습니다. 또한 기본적으로 CORS는 교차 출처 요청에 쿠키를 포함하지 않으며 이로 인해 교차 사이트 요청 위조 또는 CSRF라고하는 취약성이 발생할 수 있습니다. CORS에서 CSRF 취약성의 가능성을 줄이기 위해 CORS는 요청에 쿠키를 포함해도 괜찮다는 것을 서버와 클라이언트가 모두 인정해야합니다.

Access-Control-Expose-Headers (Response header)는 노출해도 안전한 헤더를 나타냅니다. 응답의 헤더를 읽을 수있는 목록입니다. 기본적으로 6 개의 단순 응답 헤더 (Cache-Control, Content-Language, Content-Type, Expires, Last-Modified, Pragma) 만 노출됩니다.

Access-Control-Request-Headers (Request Header)는 실제 요청 중에 사용할 수있는 HTTP 헤더를 나타냅니다.

origin = true (Request Header)는 요청 출처를 반영합니다. 거짓이면 Cors가 비활성화됩니다.

참고 URL : https://stackoverflow.com/questions/7067966/why-doesnt-adding-cors-headers-to-an-options-route-allow-browsers-to-access-my

반응형