CORS: Không thể sử dụng ký tự đại diện trong Access-Control-Allow-Origin khi cờ thông tin xác thực là đúng


296

Tôi có một thiết lập liên quan đến

Máy chủ giao diện (Node.js, tên miền: localhost: 3000) <---> Phần cuối (Django, Ajax, tên miền: localhost: 8000)

Trình duyệt <- webapp <- Node.js (Phục vụ ứng dụng)

Trình duyệt (webapp) -> Ajax -> Django (Phục vụ các yêu cầu POST ajax)

Bây giờ, vấn đề của tôi ở đây là với thiết lập CORS mà ứng dụng web sử dụng để thực hiện các cuộc gọi Ajax đến máy chủ phụ trợ. Trong chrome, tôi tiếp tục nhận được

Không thể sử dụng ký tự đại diện trong Access-Control-Allow-Origin khi cờ thông tin xác thực là đúng.

cũng không hoạt động trên firefox.

Thiết lập Node.js của tôi là:

var allowCrossDomain = function(req, res, next) {
    res.header('Access-Control-Allow-Origin', 'http://localhost:8000/');
    res.header('Access-Control-Allow-Credentials', true);
    res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE');
    res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
    next();
};

Và trong Django tôi đang sử dụng phần mềm trung gian này cùng với cái này

Các ứng dụng web thực hiện các yêu cầu như vậy:

$.ajax({
    type: "POST",
    url: 'http://localhost:8000/blah',
    data: {},
    xhrFields: {
        withCredentials: true
    },
    crossDomain: true,
    dataType: 'json',
    success: successHandler
});

Vì vậy, các tiêu đề yêu cầu mà webapp gửi trông giống như:

Access-Control-Allow-Credentials: true
Access-Control-Allow-Headers: "Origin, X-Requested-With, Content-Type, Accept"
Access-Control-Allow-Methods: 'GET,PUT,POST,DELETE'
Content-Type: application/json 
Accept: */*
Accept-Encoding: gzip,deflate,sdch
Accept-Language: en-US,en;q=0.8
Cookie: csrftoken=***; sessionid="***"

Và đây là tiêu đề phản hồi:

Access-Control-Allow-Headers: Content-Type,*
Access-Control-Allow-Credentials: true
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: POST,GET,OPTIONS,PUT,DELETE
Content-Type: application/json

Tôi làm sai ở đâu?!

Chỉnh sửa 1: Tôi đã sử dụng chrome --disable-web-security, nhưng bây giờ muốn mọi thứ thực sự hoạt động.

Chỉnh sửa 2: Trả lời:

Vì vậy, giải pháp cho tôi django-cors-headerscấu hình:

CORS_ORIGIN_ALLOW_ALL = False
CORS_ALLOW_CREDENTIALS = True
CORS_ORIGIN_WHITELIST = (
    'http://localhost:3000' # Here was the problem indeed and it has to be http://localhost:3000, not http://localhost:3000/
)

1
Đối với tôi, đó là localhost: 3000 không có http, như thế này: CORS_ORIGIN_WHITELIST = ('localhost: 3000',)
Andrei

Bạn có nghĩa là bạn sử dụng phát triển frontend và backend trong một PC?
fanhualuojin154873

Làm thế nào về frontend và phụ trợ trong PC khác nhau?
fanhualuojin154873

@ixaxaar tại sao bạn nói với http làm việc cho bạn? tất cả chúng ta chỉ có `'localhost: 3000'` hoạt động.
244boy

@ 244boy vâng, điểm không phải là http, nó là /cuối cùng. Tôi cho rằng bỏ qua http có thể hoạt động, nhưng tôi đã không thực sự làm việc với công cụ này trong một số năm, vì vậy không thực sự biết những gì hoạt động bây giờ!
ixaxaar 17/03/18

Câu trả lời:


247

Đây là một phần của bảo mật, bạn không thể làm điều đó. Nếu bạn muốn cho phép thông tin đăng nhập thì bạn Access-Control-Allow-Originkhông được sử dụng *. Bạn sẽ phải xác định chính xác giao thức + tên miền + cổng. Để tham khảo xem những câu hỏi sau:

  1. Các tên miền, cổng và giao thức ký tự đại diện Access-Control-Allow-Origin
  2. Chia sẻ tài nguyên nguồn gốc chéo với thông tin xác thực

Bên cạnh đó *là quá cho phép và sẽ đánh bại việc sử dụng thông tin đăng nhập. Vì vậy, đặt http://localhost:3000hoặc http://localhost:8000là tiêu đề gốc cho phép.


45
Nhưng nếu có nhiều hơn một tên miền thì sao?
aroth

13
@aroth Bạn có thể đưa ra một danh sách các tên miền. Câu hỏi liên quan: stackoverflow.com/questions/1653308/
Mạnh

13
@ user568109 Bạn có thể giải thích "Bên cạnh đó *là quá dễ dãi và sẽ đánh bại việc sử dụng thông tin đăng nhập."?
Hugo Wood

12
"Miền chính xác" là gì nếu yêu cầu đến từ thiết bị di động, giống như nó có thể xảy ra với Cordova?
Christian

8
@Christian hơi cũ, nhưng nếu ai vẫn tò mò thì vấn đề này chỉ xảy ra với các ứng dụng chạy trên trình duyệt, vì lỗi này bị trình duyệt ném vì lý do bảo mật. Các ứng dụng khách khác như ứng dụng di động, người đưa thư hoặc bất kỳ mã phụ trợ nào khác sử dụng ứng dụng khách http để thực hiện yêu cầu sẽ không gặp phải vấn đề này, vì vậy bạn không phải lo lắng về nguồn gốc và tên miền chính xác .
Alisson

32

Nếu bạn đang sử dụng phần mềm trung gian CORS và bạn muốn gửi withCredentialboolean true, bạn có thể định cấu hình CORS như thế này:

var cors = require('cors');    
app.use(cors({credentials: true, origin: 'http://localhost:3000'}));

16

Nếu bạn đang sử dụng, expressbạn có thể sử dụng gói cors để cho phép CORS như vậy thay vì viết phần mềm trung gian của bạn;

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

app.use(cors());

app.get(function(req,res){ 
  res.send('hello');
});

12
À, bây giờ điều đó thuận tiện hơn, tuy nhiên, kết quả là như nhau :( BTW, tôi đang sử dụngapp.use(cors({credentials: true}));
ixaxaar

1
Bạn có thể muốn xem xét này middleware Django CORS được thử nghiệm.
Bulkan

1
Vì vậy, bạn có hai phần mềm trung gian Django? Tôi sẽ chỉ sử django-cors-headerdụng ứng dụng. Đảm bảo bạn thêm localhost vào CORS_ORIGIN_WHITELISTcài đặt và đặt CORS_ALLOW_CREDENTIALSthànhTrue
Bulkan

1
Vâng, anh bạn, đã thử điều đó trước đây nhưng không có kết quả CORS_ORIGIN_ALLOW_ALL = True, CORS_ORIGIN_WHITELIST = ( 'localhost' )CORS_ALLOW_CREDENTIALS = True tôi đã nhận được những tiêu đề này:Access-Control-Allow-Credentials: true Access-Control-Allow-Origin: http://localhost:3000/ Access-Control-Allow-Methods: POST,GET,OPTIONS,PUT,DELETE Content-Type: application/json
ixaxaar

5
Sau khi đọc tài liệu này: github.com/expressjs/corsuse tôi sử dụng cấu hình này: app.use (cors ({thông tin đăng nhập: true, origin: ' localhost: 3001 '})); đang làm việc cho tôi
allel

11

thử nó:

const cors = require('cors')

const corsOptions = {
    origin: 'http://localhost:4200',
    credentials: true,

}
app.use(cors(corsOptions));

6

Nếu bạn muốn cho phép tất cả các nguồn gốc và giữ thông tin xác thực, điều này có hiệu quả với tôi:

app.use(cors({
  origin: function(origin, callback){
    return callback(null, true);
  },
  optionsSuccessStatus: 200,
  credentials: true
}));

@TSlegaitis Haha vâng đó là lý do tại sao nó hoạt động cho tất cả các nguồn gốc nhưng vẫn giữ thông tin đăng nhập. Tôi sẽ không đề nghị nó để bảo mật nhưng nó hoạt động.
Squirrl

2

(Chỉnh sửa) Tiện ích được đề xuất trước đó không còn khả dụng nữa, bạn có thể thử tiện ích bổ sung khác


Đối với mục đích phát triển trong Chrome, cài đặt tiện ích bổ sung này sẽ thoát khỏi lỗi cụ thể đó:

Access to XMLHttpRequest at 'http://192.168.1.42:8080/sockjs-node/info?t=1546163388687' 
from origin 'http://localhost:8080' has been blocked by CORS policy: The value of the 
'Access-Control-Allow-Origin' header in the response must not be the wildcard '*' 
when the request's credentials mode is 'include'. The credentials mode of requests 
initiated by the XMLHttpRequest is controlled by the withCredentials attribute.

Sau khi cài đặt, hãy đảm bảo bạn thêm mẫu url của mình vào Intercepted URLsbằng cách nhấp vào biểu tượng của AddOn ( CORS , xanh hoặc đỏ) và điền vào hộp văn bản thích hợp. Một mẫu URL mẫu để thêm vào đây sẽ hoạt động với http://localhost:8080:*://*


Tôi đã nhận nó ngay sau khi cài đặt nó, bất kỳ ý tưởng?
Jalil

Nó làm việc cho tôi. Cảnh báo nếu bạn có các tiện ích bổ sung tương tự khác, bạn phải gỡ cài đặt nó trước khi thử tiện ích này.
FilippoG

vui lòng sửa liên kết bị hỏng
Luk Aron

Có vẻ như phần bổ sung ban đầu đã bị xóa, tôi đã thêm một đề xuất mới dưới dạng (Chỉnh sửa) ở đầu
eriel marimon

1

Điều này giúp tôi phát triển nhưng tôi không thể khuyên rằng trong sản xuất, đó chỉ là một cách khác để hoàn thành công việc chưa được đề cập nhưng có lẽ không phải là tốt nhất. Dù sao đi đây:

Bạn có thể lấy nguồn gốc từ yêu cầu, sau đó sử dụng nó trong tiêu đề phản hồi. Đây là cách nó thể hiện trong thể hiện:

app.use(function(req, res, next) {
  res.header('Access-Control-Allow-Origin', req.header('origin') );
  next();
});

Tôi không biết nó sẽ trông như thế nào với thiết lập python của bạn nhưng điều đó sẽ dễ dịch.


Mozilla Dev Docs mở rộng ý tưởng thay đổi nguồn gốc được phép thành nguồn gốc từ yêu cầu. Bạn nên thêm tiêu đề phản hồi HTTP 'Vary: Origin' và danh sách được cho phép trong danh sách trắng.
Ramzis
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.