ไม่มี 'การเข้าถึงการควบคุมอนุญาตให้กำเนิด' - ปัญหาพอร์ต Node / Apache


260

ฉันสร้าง API ขนาดเล็กโดยใช้ Node / Express และพยายามดึงข้อมูลโดยใช้ Angularjs แต่เนื่องจากหน้า html ของฉันทำงานภายใต้ apache บน localhost: 8888 และ API ของโหนดรับฟังบนพอร์ต 3000 ฉันได้รับ 'การควบคุมการเข้าถึง - ไม่ อนุญาตให้-กำเนิด ฉันพยายามใช้ node-http-proxyและ Vhosts Apache แต่ไม่ค่อยประสบความสำเร็จโปรดดูข้อผิดพลาดและรหัสด้านล่าง

XMLHttpRequest ไม่สามารถโหลด localhost: 3000 ไม่มีส่วนหัว 'Access-Control-Allow-Origin' บนทรัพยากรที่ร้องขอ Origin 'localhost: 8888' จึงไม่ได้รับอนุญาตให้เข้าถึง "

// Api Using Node/Express    
var express = require('express');
var app = express();
var contractors = [
    {   
     "id": "1", 
        "name": "Joe Blogg",
        "Weeks": 3,
        "Photo": "1.png"
    }
];

app.use(express.bodyParser());

app.get('/', function(req, res) {
  res.json(contractors);
});
app.listen(process.env.PORT || 3000);
console.log('Server is running on Port 3000')

รหัสเชิงมุม

angular.module('contractorsApp', [])
.controller('ContractorsCtrl', function($scope, $http,$routeParams) {

   $http.get('localhost:3000').then(function(response) {
       var data = response.data;
       $scope.contractors = data;
   })

HTML

<body ng-app="contractorsApp">
    <div ng-controller="ContractorsCtrl"> 
        <ul>
            <li ng-repeat="person in contractors">{{person.name}}</li>
        </ul>
    </div>
</body>

คำตอบ:


621

ลองเพิ่มมิดเดิลแวร์ต่อไปนี้ในแอป NodeJS / Express ของคุณ (ฉันได้เพิ่มความคิดเห็นเพื่อความสะดวกของคุณ):

// Add headers
app.use(function (req, res, next) {

    // Website you wish to allow to connect
    res.setHeader('Access-Control-Allow-Origin', 'http://localhost:8888');

    // Request methods you wish to allow
    res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, PUT, PATCH, DELETE');

    // Request headers you wish to allow
    res.setHeader('Access-Control-Allow-Headers', 'X-Requested-With,content-type');

    // Set to true if you need the website to include cookies in the requests sent
    // to the API (e.g. in case you use sessions)
    res.setHeader('Access-Control-Allow-Credentials', true);

    // Pass to next layer of middleware
    next();
});

หวังว่าจะช่วย!


2
คุณช่วยระบุได้อย่างแม่นยำว่าจะไปที่ไหน ฉันมีรหัสต่อไปนี้ในเซิร์ฟเวอร์ของฉัน หลังจากนี้ไปแล้วเหรอ? แอป var = ต้องการ ('ด่วน') (), เซิร์ฟเวอร์ = ต้องการ ('http'). createServer (แอป), io = ต้องการ ('socket.io') ฟัง (เซิร์ฟเวอร์), ร้องขอ = ต้องการ ("คำขอ") , url = ต้องการ ("url"); server.listen (6969); // ไปที่นี่ไหม? ในบรรทัดใหม่
Art Geigel

1
@ jvandemo ฉันต้องเปลี่ยน app.get ('/', ฟังก์ชั่น (req, res) เป็น ... ฟังก์ชั่น (req, res, ต่อไป)?
Sangram Singh

10
ตอนนี้คุณเป็นคนโปรดของฉันแล้ว ขอบคุณ. เราสามารถเพิ่มหมายเหตุว่ารหัสนี้จะต้องเกิดขึ้นก่อนที่เส้นทางจะถูกกำหนดไว้สำหรับ noobs อย่างฉันหรือไม่?
gegillam

1
วิธีทำให้มันใช้งานได้ในขณะที่ใช้โมดูลคำขอ?
Rohit Tigga

2
มันไม่ทำงานในกรณีของฉัน ยังคงได้รับข้อผิดพลาดนี้: "การตอบสนองต่อคำขอ preflight ไม่ผ่านการตรวจสอบการควบคุมการเข้าถึง: ไม่มีส่วนหัว 'การเข้าถึงการควบคุมการอนุญาตให้มีแหล่งกำเนิด' อยู่ในทรัพยากรที่ร้องขอดังนั้นจึงไม่อนุญาตให้มีการกำเนิด ' abc.xyz.net:212 ' การเข้าถึงการตอบสนองมีรหัสสถานะ HTTP 500 "
user1451111

96

คำตอบที่ยอมรับนั้นใช้ได้ในกรณีที่คุณต้องการบางสิ่งที่สั้นกว่านี้คุณสามารถใช้ปลั๊กอินชื่อcorsสำหรับ Express.js

มันใช้ง่ายสำหรับกรณีนี้โดยเฉพาะ:

var cors = require('cors');

// use it before all route definitions
app.use(cors({origin: 'http://localhost:8888'}));

3
ฉันต้องใช้{origin: 'null'}เพื่อให้มันทำงาน ... เห็นได้ชัดว่าเบราว์เซอร์ของฉันส่งnullเป็นจุดเริ่มต้นหรือไม่
Ricardo Cruz

2
ทำไมต้องบูรณาการล้อ ฉันมักจะหาวิธีการแก้ปัญหาบรรจุเทียบข้อมูลโค้ด
ปิแอร์

ห้องสมุดเล็ก ๆ ที่น่ารักที่จัดการกรณีการใช้งานของฉันที่ต้องการวิธีการที่แตกต่างจากต้นกำเนิดที่แตกต่างกันค่อนข้างดี ... และความเหนื่อยล้าของรหัสน้อยลงสำหรับคนต่อไปมอง
Kyle Baker

6
ขอบคุณapp.use(cors({origin: '*'}));ทำงานให้ฉันเป็นต่อenable-ล
danialk

2
ฉันขอแนะนำให้ดูที่หน้าnpm corsเพื่อให้ใช้งานได้ดีขึ้น มันทำให้สิ่งต่าง ๆ ชัดเจนสำหรับฉัน =)
13013SwagR

30

อีกวิธีคือเพียงเพิ่มส่วนหัวในเส้นทางของคุณ:

router.get('/', function(req, res) {
    res.setHeader('Access-Control-Allow-Origin', '*');
    res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, PUT, PATCH, DELETE'); // If needed
    res.setHeader('Access-Control-Allow-Headers', 'X-Requested-With,content-type'); // If needed
    res.setHeader('Access-Control-Allow-Credentials', true); // If needed

    res.send('cors problem fixed:)');
});

8
)จากรอยยิ้มทำให้ฉันสับสน
diEcho

17

คำตอบด้านบนทำงานที่ดีสำหรับฉันยกเว้นว่าผมจำเป็นต้องมีรายการที่อนุญาตมากกว่าหนึ่งโดเมน

นอกจากนี้คำตอบยอดนิยมยังได้รับความเดือดร้อนจากความจริงที่ว่าOPTIONSมิดเดิลแวร์ไม่ได้รับการร้องขอและคุณไม่ได้รับการร้องขอโดยอัตโนมัติ

ฉันเก็บโดเมนที่allowed_originsอยู่ในรายการที่อนุญาตเช่นเดียวกับในการกำหนดค่าด่วนและวางโดเมนที่ถูกต้องตามoriginส่วนหัวเนื่องจากAccess-Control-Allow-Originไม่อนุญาตให้ระบุมากกว่าหนึ่งโดเมน

นี่คือสิ่งที่ฉันลงเอยด้วย:

var _ = require('underscore');

function allowCrossDomain(req, res, next) {
  res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS');

  var origin = req.headers.origin;
  if (_.contains(app.get('allowed_origins'), origin)) {
    res.setHeader('Access-Control-Allow-Origin', origin);
  }

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

app.configure(function () {
  app.use(express.logger());
  app.use(express.bodyParser());
  app.use(allowCrossDomain);
});

นี่คือ 'if (app.get (' origins ที่อนุญาต ') indexOf (origin)! == - 1) หรือไม่?
Rune Jeppesen

13

รหัสคำตอบอนุญาตเฉพาะ localhost: 8888 รหัสนี้ไม่สามารถปรับใช้กับการผลิตหรือชื่อเซิร์ฟเวอร์และพอร์ตอื่น

ในการทำให้มันใช้งานได้กับทุกแหล่งให้ใช้สิ่งนี้แทน:

// Add headers
app.use(function (req, res, next) {

    // Website you wish to allow to connect
    res.setHeader('Access-Control-Allow-Origin', '*');

    // Request methods you wish to allow
    res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, PUT, PATCH, DELETE');

    // Request headers you wish to allow
    res.setHeader('Access-Control-Allow-Headers', 'X-Requested-With,content-type');

    // Set to true if you need the website to include cookies in the requests sent
    // to the API (e.g. in case you use sessions)
    res.setHeader('Access-Control-Allow-Credentials', true);

    // Pass to next layer of middleware
    next();
});

2
มันไม่ได้ผลสำหรับฉัน! "* ไม่ใช่ต้นกำเนิดที่ถูกต้อง" ดูเหมือนว่าอักขระ * ไม่ได้รับการยอมรับว่าเป็นอักขระตัวแทน
ฟรานเชสโก้

มันใช้งานได้สำหรับฉัน เช่นใช้ wild card '*' ใช้งานได้ทั้งโครเมี่ยมและซาฟารี
AnBisw

ขอบคุณ;) ทำงานได้ดี
Mauro

9

ติดตั้ง cors พึ่งพาในโครงการของคุณ:

npm i --save cors

เพิ่มไปยังไฟล์คอนฟิกูเรชันเซิร์ฟเวอร์ของคุณดังต่อไปนี้:

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

มันใช้งานได้สำหรับฉันด้วยรุ่น 2.8.4 cors


"cors": "^2.8.5", "express": "^4.16.3",ทำงานได้ดีเพียงแค่มีบรรทัด @monikaja แนะนำ ขอบคุณ!
RamiroIsBack

สิ่งนี้ทำเพื่อเปิดใช้งานต้นกำเนิด / โดเมนทั้งหมดเพื่อเข้าถึงแอปซึ่งเป็นสิ่งที่คุณไม่ต้องการทำ แทนที่จะระบุเฉพาะโดเมนที่อนุญาต
Lacho Tomov

7

สิ่งนี้ใช้ได้สำหรับฉัน

app.get('/', function (req, res) {

    res.header("Access-Control-Allow-Origin", "*");
    res.send('hello world')
})

คุณสามารถเปลี่ยน * เพื่อให้เหมาะกับความต้องการของคุณ หวังว่านี่จะช่วยได้


7

สวัสดีสิ่งนี้เกิดขึ้นเมื่อส่วนหน้าและส่วนหลังทำงานบนพอร์ตที่ต่างกัน เบราว์เซอร์บล็อกการตอบสนองจากส่วนหลังเนื่องจากไม่มีส่วนหัว CORS วิธีแก้ไขคือเพิ่มส่วนหัว CORS ในคำขอแบ็กเอนด์ วิธีที่ง่ายที่สุดคือใช้แพ็คเกจ cors npm

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

สิ่งนี้จะเปิดใช้งานส่วนหัว CORS ในคำขอทั้งหมดของคุณ สำหรับข้อมูลเพิ่มเติมคุณสามารถดูเอกสารประกอบ cors

https://www.npmjs.com/package/cors


3
app.all('*', function(req, res,next) {
    /**
     * Response settings
     * @type {Object}
     */
    var responseSettings = {
        "AccessControlAllowOrigin": req.headers.origin,
        "AccessControlAllowHeaders": "Content-Type,X-CSRF-Token, X-Requested-With, Accept, Accept-Version, Content-Length, Content-MD5,  Date, X-Api-Version, X-File-Name",
        "AccessControlAllowMethods": "POST, GET, PUT, DELETE, OPTIONS",
        "AccessControlAllowCredentials": true
    };

    /**
     * Headers
     */
    res.header("Access-Control-Allow-Credentials", responseSettings.AccessControlAllowCredentials);
    res.header("Access-Control-Allow-Origin",  responseSettings.AccessControlAllowOrigin);
    res.header("Access-Control-Allow-Headers", (req.headers['access-control-request-headers']) ? req.headers['access-control-request-headers'] : "x-requested-with");
    res.header("Access-Control-Allow-Methods", (req.headers['access-control-request-method']) ? req.headers['access-control-request-method'] : responseSettings.AccessControlAllowMethods);

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


});

2

เพิ่มรหัสต่อไปนี้ใน app.js ของ NODEJ Resti api เพื่อหลีกเลี่ยงข้อผิดพลาด "Access-Control-Allow-Origin" ในมุม 6 หรือกรอบงานอื่น ๆ

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
}));

1

คุณสามารถใช้ "$ http.jsonp"

หรือ

ด้านล่างนี้เป็นวิธีแก้ไขสำหรับ chrome สำหรับการทดสอบในท้องถิ่น

คุณต้องเปิด chrome ด้วยคำสั่งต่อไปนี้ (กดหน้าต่าง + R)

Chrome.exe --allow-file-access-from-files

หมายเหตุ: โครเมี่ยมของคุณจะต้องไม่เปิด เมื่อคุณเรียกใช้คำสั่งนี้ chrome จะเปิดโดยอัตโนมัติ

หากคุณกำลังป้อนคำสั่งนี้ในพร้อมท์คำสั่งให้เลือกไดเรกทอรีการติดตั้ง chrome แล้วใช้คำสั่งนี้

ด้านล่างรหัสสคริปต์สำหรับโครเมี่ยมแบบเปิดใน MAC ด้วย "--allow-file-access-from-files"

set chromePath to POSIX path of "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome" 
set switch to " --allow-file-access-from-files"
do shell script (quoted form of chromePath) & switch & " > /dev/null 2>&1 &"

ตัวเลือกที่สอง

คุณสามารถใช้open (1)เพื่อเพิ่มค่าสถานะ: open -a 'Google Chrome' - ด้านล่าง - อนุญาตให้เข้าถึงไฟล์จากไฟล์


วิธีการเกี่ยวกับ MAC? Chrome.exe - อนุญาตให้เข้าถึงไฟล์จากไฟล์
user1336103

/ Applications / Google \ Chrome.app/Contents/MacOS/Google \ Chrome - อนุญาตให้เข้าถึงไฟล์จากไฟล์จัดการเพื่อเปิด chrome แต่ข้อความยังคงแสดง "XMLHttpRequest ไม่สามารถโหลดlocalhost: 3000 Origin localhost: 8888คือ ไม่ได้รับอนุญาตจาก Access-Control-Allow-Origin "
1336103

+1 ฉันสามารถยืนยันการทำงานกับตัวเลือก Mac โดยใช้ 'เปิด' เคสของฉันแตกต่างกันเล็กน้อยเนื่องจากฉันทดสอบไซต์ที่ดาวน์โหลดอย่างสมบูรณ์ซึ่งเข้าถึงไฟล์ JSON ท้องถิ่นบางตัว
spong

0

/**
 * Allow cross origin to access our /public directory from any site.
 * Make sure this header option is defined before defining of static path to /public directory
 */
expressApp.use('/public',function(req, res, next) {
    res.setHeader("Access-Control-Allow-Origin", "*");
    // Request headers you wish to allow
    res.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
    // Set to true if you need the website to include cookies in the requests sent
    res.setHeader('Access-Control-Allow-Credentials', true);
    // Pass to next layer of middleware
    next();
});


/**
 * Server is about set up. Now track for css/js/images request from the 
 * browser directly. Send static resources from "./public" directory. 
 */
expressApp.use('/public', express.static(path.join(__dirname, 'public')));
If you want to set Access-Control-Allow-Origin to a specific static directory you can set the following.

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.