Không có 'Kiểm soát truy cập-Cho phép-Xuất xứ' - Sự cố cổng Node / Apache


260

Tôi đã tạo một API nhỏ bằng Node / Express và cố gắng kéo dữ liệu bằng Angularjs nhưng vì trang html của tôi đang chạy dưới apache trên localhost: 8888 và API nút đang lắng nghe trên cổng 3000, tôi đang nhận được No 'Control-Control- Cho phép xuất xứ '. Tôi đã thử sử dụng node-http-proxyvà Vhosts Apache nhưng không có nhiều thành công, vui lòng xem đầy đủ lỗi và mã bên dưới.

XMLHttpRequest không thể tải localhost: 3000. Không có tiêu đề 'Kiểm soát truy cập-Cho phép-Xuất xứ' trên tài nguyên được yêu cầu. Do đó, nguồn gốc 'localhost: 8888' không được phép truy cập. "

// 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')

Mã góc

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>

Câu trả lời:


622

Hãy thử thêm phần mềm trung gian sau vào ứng dụng NodeJS / Express của bạn (Tôi đã thêm một số nhận xét để thuận tiện cho bạn):

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

Mong rằng sẽ giúp!


2
Bạn có thể giúp xác định chính xác nơi mà đi? Tôi có mã sau đây trong máy chủ của tôi. Nó đi ngay sau này? var app = quiries ('express') (), server = quiries ('http'). createdServer (app), io = quiries ('socket.io') , url = yêu cầu ("url"); máy chủ.listen (6969); // nó có ở đây không? trên một dòng mới?
Art Geigel

1
@jvandemo tôi có phải thay đổi app.get ('/', hàm (req, res) thành ... hàm (req, res, next) không?
Sangram Singh

10
Bạn là người yêu thích của tôi ngay bây giờ. Cảm ơn bạn. Chúng ta có thể thêm một lưu ý rằng mã này phải xảy ra trước khi các tuyến đường được xác định cho những người không như tôi không?
gegillam

1
Làm thế nào để thực hiện công việc này trong khi sử dụng mô-đun yêu cầu?
Rohit Tigga

2
Nó không hoạt động trong trường hợp của tôi. Vẫn nhận được lỗi này: "Phản hồi yêu cầu preflight không vượt qua kiểm tra kiểm soát truy cập: Không có tiêu đề 'Kiểm soát truy cập-Cho phép-Xuất xứ' trên tài nguyên được yêu cầu. Do đó , ' abc.xyz.net:212 ' không được phép truy cập. Phản hồi có mã trạng thái HTTP 500. "
user1451111

96

Câu trả lời được chấp nhận là tốt, trong trường hợp bạn thích một cái gì đó ngắn hơn, bạn có thể sử dụng một plugin có tên là cors có sẵn cho Express.js

Thật đơn giản để sử dụng, trong trường hợp cụ thể này:

var cors = require('cors');

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

3
Tôi đã phải sử dụng {origin: 'null'}nó để hoạt động ... Rõ ràng, trình duyệt của tôi gửi nullnhư là nguồn gốc?
Ricardo Cruz

2
Tại sao phải phát minh lại bánh xe. Tôi luôn luôn cho một giải pháp đóng gói so với đoạn mã
Pierre

thư viện nhỏ ngọt ngào xử lý trường hợp sử dụng của tôi muốn các phương thức khác nhau từ các nguồn gốc khác nhau khá độc đáo ... và ít mệt mỏi mã hơn cho người tiếp theo nhìn vào nó.
Kyle Baker

6
Cảm ơn, app.use(cors({origin: '*'}));đã làm việc cho tôi, theo kích hoạt .
danialk

2
Tôi đề nghị nên xem trang npm cors để sử dụng nó tốt hơn. Nó làm cho mọi thứ rất rõ ràng đối với tôi =).
13013SwagR 17/03/19

30

Một cách khác, chỉ đơn giản là thêm các tiêu đề vào tuyến đường của bạn:

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
)của Smiley làm tôi bối rối
diEcho

17

Các đầu câu trả lời đã làm việc tốt cho tôi, ngoại trừ rằng tôi cần phải danh sách trắng nhiều hơn một miền.

Ngoài ra, câu trả lời hàng đầu chịu đựng thực tế là OPTIONSyêu cầu không được xử lý bởi phần mềm trung gian và bạn không nhận được nó tự động.

Tôi lưu trữ các tên miền được liệt kê allowed_originstrong cấu hình Express và đặt tên miền chính xác theo origintiêu đề vì Access-Control-Allow-Originkhông cho phép chỉ định nhiều hơn một tên miền.

Đây là những gì tôi đã kết thúc với:

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

Đây có phải là 'if (app.get (' nguồn gốc được phép '). IndexOf (nguồn gốc)! == - 1) không?
Rune Jeppesen

13

Mã trả lời chỉ cho phép localhost: 8888. Mã này không thể được triển khai để sản xuất, hoặc tên máy chủ và cổng khác nhau.

Để làm cho nó hoạt động cho tất cả các nguồn, thay vào đó sử dụng:

// 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
Điều này không làm việc cho tôi! "* không phải là nguồn gốc hợp lệ". Có vẻ như ký tự * không được công nhận là ký tự đại diện.
Francesco

Nó làm việc cho tôi. tức là sử dụng thẻ hoang dã '*'. hoạt động cả cho chrome và safari.
AnBisw

Cảm ơn;) Hoạt động tốt
Mauro

9

Cài đặt phụ thuộc cors trong dự án của bạn:

npm i --save cors

Thêm vào tập tin cấu hình máy chủ của bạn như sau:

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

Nó hoạt động với tôi với phiên bản 2.8.4 cors.


"cors": "^2.8.5", "express": "^4.16.3",hoạt động tốt chỉ với dòng @monikaja đề xuất. Cảm ơn!
RamiroIsBack

Điều này làm là cho phép tất cả các nguồn gốc / tên miền truy cập vào ứng dụng, điều mà bạn thường không muốn làm. Thay vào đó chỉ định các miền được phép.
Lacho Tomov

7

Điều này làm việc cho tôi.

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

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

Bạn có thể thay đổi * để phù hợp với nhu cầu của bạn. Hy vọng điều này có thể giúp đỡ.


7

Xin chào, điều này xảy ra khi giao diện người dùng và phụ trợ đang chạy trên các cổng khác nhau. Trình duyệt chặn các phản hồi từ phụ trợ do không có tiêu đề CORS. Giải pháp là tạo thêm các tiêu đề CORS trong yêu cầu phụ trợ. Cách dễ nhất là sử dụng gói cpm npm.

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

Điều này sẽ cho phép các tiêu đề CORS trong tất cả các yêu cầu của bạn. Để biết thêm thông tin bạn có thể tham khảo tài liệu 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

Thêm mã sau vào app.js của NODEJ Resti api để tránh lỗi "Access-Control-Allow-Origin" ở góc 6 hoặc bất kỳ khung nào khác

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

Bạn có thể sử dụng "$ http.jsonp"

HOẶC LÀ

Dưới đây là công việc xung quanh cho chrome để thử nghiệm cục bộ

Bạn cần mở chrome của bạn bằng lệnh sau. (Nhấn cửa sổ + R)

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

Lưu ý: Chrome của bạn không được mở. Khi bạn chạy lệnh này chrome sẽ tự động mở.

Nếu bạn đang nhập lệnh này trong dấu nhắc lệnh thì hãy chọn thư mục cài đặt chrome của bạn, sau đó sử dụng lệnh này.

Bên dưới mã tập lệnh cho chrome mở trong MAC với "--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 &"

lựa chọn thứ hai

Bạn chỉ có thể sử dụng open (1) để thêm các cờ: open -a 'Google Chrome' --args --allow-file-access-from-files


Còn về MAC thì sao ?? Chrome.exe --allow-file-access-from-files
user1336103

/ Ứng dụng / Google \ Chrome.app/Contents/MacOS/Google \ Chrome --allow-file-access-from-files quản lý để mở chrome nhưng thông báo vẫn hiển thị "XMLHttpRequest không thể tải localhost: 3000. Origin localhost: 8888 là không được phép bởi Access-Control-
allow

+1 Tôi có thể xác nhận điều này hoạt động với tùy chọn Mac bằng cách sử dụng 'mở'. Trường hợp của tôi hơi khác một chút vì tôi chỉ đơn giản là đang thử nghiệm một trang web được tải xuống hoàn toàn truy cập vào một số tệp JSON cục bộ.
bọt biển

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.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.