Câu hỏi Tại sao JavaScript của tôi nhận được tiêu đề “Không có 'Access-Control-Allow-Origin' xuất hiện trên tài nguyên được yêu cầu” khi Postman không?


Tôi đang cố gắng cấp quyền sử dụng JavaScript bằng cách kết nối với Yên tĩnh  API được xây dựng trong Bình. Tuy nhiên, khi tôi thực hiện yêu cầu, tôi nhận được lỗi sau:

XMLHttpRequest không thể tải http: // myApiUrl / login. Không có tiêu đề 'Access-Control-Allow-Origin' xuất hiện trên tài nguyên được yêu cầu. Do đó, gốc 'null' không được phép truy cập.

Tôi biết rằng API hoặc tài nguyên từ xa phải đặt tiêu đề, nhưng tại sao nó lại hoạt động khi tôi thực hiện yêu cầu thông qua tiện ích của Chrome Người phát thơ?

Đây là mã yêu cầu:

$.ajax({
    type: "POST",
    dataType: 'text',
    url: api,
    username: 'user',
    password: 'pass',
    crossDomain : true,
    xhrFields: {
        withCredentials: true
    }
})
    .done(function( data ) {
        console.log("done");
    })
    .fail( function(xhr, textStatus, errorThrown) {
        alert(xhr.responseText);
        alert(textStatus);
    });

1869
2017-11-17 19:29


gốc


Bạn có đang thực hiện yêu cầu từ máy chủ cục bộ hoặc thực thi HTML không? - MD. Sahib Bin Mahboob
@ MD.SahibBinMahboob Nếu tôi hiểu câu hỏi của bạn tôi yêu cầu từ localhost - Tôi có trang trên máy tính của tôi và chỉ cần chạy nó. Khi tôi triển khai trang web trên lưu trữ, nó cho kết quả tương tự. - Mr Jedi
tên miền của trang được thực hiện của bạn và tên miền được yêu cầu giống hoặc khác nhau là gì? - MD. Sahib Bin Mahboob
nhiều liên quan: stackoverflow.com/questions/10143093/… - cregox
Đối với bất kỳ ai muốn đọc thêm, MDN có một bài viết hay về tất cả các yêu cầu về ajax và cross origin: developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS - Sam Eaton


Các câu trả lời:


Nếu tôi hiểu nó đúng, bạn đang làm một XMLHttpRequest đến một tên miền khác với trang của bạn đang bật. Vì vậy, trình duyệt chặn nó vì nó thường cho phép một yêu cầu có cùng nguồn gốc vì lý do bảo mật. Bạn cần phải làm điều gì đó khác khi bạn muốn thực hiện yêu cầu tên miền chéo. Hướng dẫn về cách đạt được điều đó là Sử dụng CORS.

Khi bạn đang sử dụng người đưa thư, họ không bị giới hạn bởi chính sách này. Trích dẫn từ XMLHttpRequest có nguồn gốc chéo:

Các trang web thông thường có thể sử dụng đối tượng XMLHttpRequest để gửi và nhận dữ liệu từ các máy chủ từ xa, nhưng chúng bị giới hạn bởi cùng một chính sách gốc. Tiện ích mở rộng không quá giới hạn. Một phần mở rộng có thể nói chuyện với các máy chủ từ xa bên ngoài nguồn gốc của nó, miễn là nó có yêu cầu quyền gốc chéo.


1008
2017-11-17 19:49



Bạn đúng. Tôi yêu cầu tên miền khác với trang của tôi. API nằm trên máy chủ và tôi chạy yêu cầu từ máy chủ cục bộ. Trước khi tôi chấp nhận câu trả lời, bạn có thể giải thích cho tôi ý nghĩa của việc "thực hiện yêu cầu trực tiếp" không? POSTMAN không sử dụng tên miền? - Mr Jedi
Trình duyệt không chặn yêu cầu. Các trình duyệt duy nhất chặn hoàn toàn các yêu cầu ajax bắt nguồn từ IE7 trở lên. Tất cả các trình duyệt, ngoài IE7 và cũ hơn, thực hiện các đặc tả CORS (IE8 & IE9 một phần). Tất cả những gì bạn cần làm là chọn tham gia các yêu cầu CORS trên máy chủ API của bạn bằng cách trả về các tiêu đề phù hợp dựa trên yêu cầu. Bạn nên đọc các khái niệm CORS tại mzl.la/VOFrSz. Postman cũng gửi yêu cầu qua XHR. Nếu bạn không nhìn thấy cùng một vấn đề khi sử dụng người đưa thư, điều này có nghĩa là bạn vô tình không gửi cùng một yêu cầu qua bưu điện. - Ray Nicholus
@ MD.SahibBinMahboob Postman KHÔNG gửi yêu cầu "từ mã java / python" của bạn. Nó đang gửi yêu cầu trực tiếp từ trình duyệt. XHR trong các tiện ích của Chrome hoạt động hơi khác một chút, đặc biệt là khi các yêu cầu có nguồn gốc chéo có liên quan. - Ray Nicholus
@ đó là trình duyệt thực sự áp đặt quy tắc. Vì vậy, bắt đầu yêu cầu từ bất kỳ nơi nào thay vì trình duyệt sẽ hoạt động - MD. Sahib Bin Mahboob
@ SuhailGupta, nếu bạn cho phép xuất xứ trong máy chủ của mình, nó sẽ được phép thực hiện yêu cầu mà thực sự được gọi là CORS. - MD. Sahib Bin Mahboob


Đây không phải là bản sửa lỗi cho sản xuất hoặc khi ứng dụng phải được hiển thị cho khách hàng, điều này chỉ hữu ích khi giao diện người dùng và chương trình phụ trợ phát triển  khác nhau máy chủ và trong sản xuất, chúng thực sự trên cùng một máy chủ. Ví dụ: Trong khi phát triển giao diện người dùng cho bất kỳ ứng dụng nào nếu có nhu cầu kiểm tra nó cục bộ, hãy trỏ nó đến máy chủ phụ trợ, trong trường hợp đó, đây là bản sửa lỗi hoàn hảo. Để sửa lỗi sản xuất, các tiêu đề CORS phải được thêm vào máy chủ phụ trợ để cho phép truy cập nguồn gốc chéo.

Cách dễ dàng là chỉ cần thêm phần mở rộng trong google chrome để cho phép truy cập bằng CORS.

(https://chrome.google.com/webstore/detail/allow-control-allow-origi/nlfbmbojpeacfghkpbjhddihlkkiljbi?hl=vi-VN)

Chỉ cần bật tiện ích này bất cứ khi nào bạn muốn cho phép truy cập không 'truy cập-kiểm soát-cho phép-xuất xứ' yêu cầu tiêu đề.

Hoặc là 

Trong Windows, hãy dán lệnh này vào chạy cửa sổ

chrome.exe --user-data-dir="C:/Chrome dev session" --disable-web-security

điều này sẽ mở ra một chrome trình duyệt cho phép truy cập không 'truy cập-kiểm soát-cho phép-xuất xứ' yêu cầu tiêu đề.


450
2018-03-04 06:42



Điều này là tuyệt vời nhưng khách hàng không thể được yêu cầu khởi chạy chrome theo cách này để thực thi yêu cầu nội bộ cho cuộc gọi webservice. - Taersious
điều này không nên được chấp nhận làm câu trả lời, cài đặt plugin của bên thứ ba để sửa ứng dụng của bạn, thay vì hiểu CORS và sửa ứng dụng của bạn, người khác sẽ sử dụng api của bạn như thế nào? bạn sẽ làm cho họ tất cả cài đặt plugin này - James Kirkby
Tôi đã cài đặt tiện ích mở rộng này và đã thực hiện một yêu cầu, so với kiểm tra yêu cầu trong trình duyệt, những điều sau đã được chỉ định -> Xuất xứ: evil.com . Có vẻ như tiện ích mở rộng này đang thay đổi Nguồn gốc thành evil.com - wagwanJahMan
Tiện ích mở rộng này hoạt động như một sự quyến rũ. Nhưng thực sự những gì họ đang làm trong nội bộ? Có cách nào để làm tương tự trong Javascript hay Jquery cách hơn là sử dụng một plugin? - sms
Tôi nghĩ đây là một câu trả lời thực sự tuyệt vời nếu bạn không cần sửa chữa vĩnh viễn hoặc nếu bạn chỉ cần tắt CORS tạm thời. Đó là những gì tôi cần, và giải pháp này hoạt động rất tốt. Rõ ràng, điều này không bao giờ có thể được coi là một giải pháp lâu dài. - jtcotton63


Nếu bạn có thể giải quyết JSON đổi lại, sau đó thử sử dụng JSONP (lưu ý P ở cuối) để nói giữa các tên miền:

$.ajax({
  type: "POST",
  dataType: 'jsonp',
  ...... etc ......

Tìm hiểu thêm về cách làm việc với JSONP đây:

Sự ra đời của JSONP - về bản chất là một bản hack script cross-site consensual - đã mở ra cánh cửa cho các mashup nội dung mạnh mẽ. Nhiều trang web nổi bật cung cấp dịch vụ JSONP, cho phép bạn truy cập vào nội dung của họ thông qua API được xác định trước.


312
2018-02-22 00:42



Hãy nhận biết jsonp không hoạt động đối với nội dung POST. Các cuộc thảo luận khác đây. - Prabu Raja
Làm thế nào điều này có rất nhiều phiếu bầu khi bạn không thể sử dụng jsonp với yêu cầu POST?!?! - fatlog
Khi bạn sử dụng JSONP, $ .ajax sẽ bỏ qua type, vì vậy nó luôn luôn GET có nghĩa là câu trả lời này sẽ luôn hoạt động. - noob
Có vẻ như hơn 200 người không nhận được nó - cs01
Cũng lưu ý rằng JSONP không thể trao đổi trực tiếp với JSON. Bạn cần máy chủ để trả về dữ liệu ở định dạng JSONP. Đơn giản chỉ cần thay đổi dataType chỉ trong cài đặt yêu cầu AJAX sẽ không hoạt động. - Rory McCrossan


Nó rất đơn giản để giải quyết nếu bạn đang sử dụng PHP. Chỉ cần thêm đoạn mã sau vào đầu trang PHP của bạn để xử lý yêu cầu:

<?php header('Access-Control-Allow-Origin: *'); ?>

Cảnh báo: Điều này có chứa một vấn đề bảo mật cho tập tin PHP của bạn mà nó có thể được gọi bởi kẻ tấn công. bạn phải sử dụng các phiên và cookie để xác thực để ngăn tệp / dịch vụ của bạn chống lại cuộc tấn công này. Dịch vụ của bạn dễ bị tổn thương giả mạo yêu cầu chéo trang (CSRF).

Nếu bạn đang sử dụng Nút đỏ bạn phải cho phép CORS trong node-red/settings.js tệp bằng cách hủy nhận xét các dòng sau:

// The following property can be used to configure cross-origin resource sharing
// in the HTTP nodes.
// See https://github.com/troygoode/node-cors#configuration-options for
// details on its contents. The following is a basic permissive set of options:
httpNodeCors: {
 origin: "*",
 methods: "GET,PUT,POST,DELETE"
},

185
2017-12-03 20:24



Câu hỏi không phải là về PHP chút nào. - mknaf
và nó không an toàn - llazzaro
Bạn không nên tắt CORS bởi vì bạn không biết những gì nó cho. Đây là một câu trả lời khủng khiếp. - meagar♦
Mặc dù nó có thể không an toàn, câu hỏi không phải là về an ninh, nhưng làm thế nào để hoàn thành nhiệm vụ. Đây là một trong các tùy chọn mà nhà phát triển phải chọn khi xử lý các yêu cầu AJAX giữa nhiều miền. Nó đã giúp tôi giải quyết vấn đề và cho đơn đăng ký của tôi, tôi không quan tâm đến dữ liệu đến từ đâu. Tôi khử trùng tất cả các đầu vào với PHP trên tên miền đích, vì vậy, nếu ai đó muốn đăng một số thư rác vào nó, hãy để họ thử. Điểm chính ở đây là, AJAX miền chéo có thể được cho phép từ miền đích. 1 cho câu trả lời. - ZurabWeb
Trong khi tôi đồng ý với thông điệp chung mà Piero đưa ra, thì đó không phải là vấn đề bảo mật, nhưng an ninh là một mối quan ngại. Tôi nghĩ rằng điều này nên có ít nhất nói một cái gì đó như "Đây thường là xấu! Đừng làm điều này trừ khi bạn biết những gì bạn đang làm! Đây là tài liệu hướng dẫn về nó: ...", và có thể giải thích ngắn gọn lý do tại sao. Tôi sẽ ghét ai đó đến đây và chỉ nghĩ "Ồ, tôi có thể thêm / điều chỉnh tiêu đề này và tôi tốt!" và không biết toàn bộ chi nhánh. Ý tôi là, nó thuộc loại họ nghiên cứu và tất cả, nhưng vẫn vậy. - Thomas F.


Tôi ước ai đó đã chia sẻ trang web này với tôi từ lâu http://cors.io/ nó sẽ tiết kiệm được rất nhiều thời gian so với việc xây dựng và dựa vào proxy của riêng tôi. Tuy nhiên, khi bạn chuyển sang sản xuất, có proxy của riêng bạn là đặt cược tốt nhất vì bạn vẫn kiểm soát tất cả các khía cạnh của dữ liệu.

Tất cả những gì bạn cần:

https://cors.io/?http://HTTP_YOUR_LINK_HERE


143
2017-07-21 22:08



Nhược điểm của điều này là gì? Có phải những kẻ đó đang chặn dữ liệu của tôi không? - Sebastialonso
cors.io/?u=HTTP_YOUR_LINK_HERE     (Điều chỉnh nhỏ) - jkpd
Tôi không nghĩ rằng việc gửi dữ liệu của bạn qua proxy của bên thứ ba là một ý tưởng hay - Daniel Alexandrov
Một nhược điểm là đôi khi chúng bị quá tải, như bây giờ. This application is temporarily over its serving quota. Please try again later. - Daniel Hickman
thử quá https://crossorigin.me/http://example.com - KingRider


Có vấn đề về tên miền chéo khi sử dụng Ajax. Bạn phải chắc chắn rằng bạn đang truy cập các tệp của mình trên cùng một http:// đường mà không có www. (hoặc truy cập từ http://www. và đăng lên cùng một đường dẫn bao gồm www.) mà trình duyệt coi là miền khác khi truy cập qua www. đường dẫn, vì vậy bạn thấy vấn đề ở đâu. Bạn đang đăng lên một miền khác và trình duyệt chặn luồng vì vấn đề gốc.

Nếu API không được đặt trên cùng một máy chủ mà bạn đang yêu cầu, luồng này bị chặn và bạn sẽ cần phải tìm cách khác để giao tiếp với API.


61
2018-03-12 08:53



yup, tôi đã buộc phải điều này trong ứng dụng phonegap của tôi, var app_url = location.protocol + '//' + location.host + '/ api /. vấn đề là trang web với www. prepended sẽ mang lại lỗi đó. - Sir Lojik


Nếu bạn đang sử dụng Node.js, thử nó:

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

Thêm thông tin: CORS trên ExpressJS


55
2018-02-12 16:27



Tôi đưa cho bạn phiếu bầu vì đây là chính xác những gì tôi cần. Nhưng nghĩ rằng nó là một ý tưởng tồi để quảng bá ví dụ "*" mà không giải thích rằng nó sẽ cho phép bất kỳ kết nối nào và không nên được sử dụng trong sản xuất. Điều này được giải thích tại liên kết MDN developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS. - rob
@rob cảm ơn cho bình luận của bạn. Bạn nói đúng, chúng ta nên xác định nguồn gốc nào được phép sử dụng tài nguyên. Nhưng trong trường hợp, các nguồn lực sử dụng cho mục đích công cộng và chúng tôi không biết người tiêu dùng, tôi nghĩ chúng ta nên đi với "*" nếu tôi không sai. - Nguyen Tran
Tôi đã sử dụng khái niệm này và vấn đề của tôi được giải quyết trong nodejs. Cảm ơn - Deepak Bhatta
app.use (function (req, res, next) {res.setHeader ('Access-Control-Allow-Origin', '*'); res.setHeader ('Access-Control-Allow-Methods', 'GET, POST , OPTIONS, PUT, PATCH, DELETE '); res.setHeader (' Access-Control-Allow-Headers ',' X-Requested-With, content-type, Authorization '); res.setHeader (' Access-Control-Allow -Credentials ', true); if (' OPTIONS '=== req.method) {res.send (204);} else {next ();}}); - Ricky sharma
Về nguy cơ sử dụng "Access-Control-Allow-Origin", "*", xem security.stackexchange.com/a/45677. tldr: Thông số W3 thực sự khuyên rằng: Tài nguyên có thể truy cập công khai, không có kiểm soát kiểm soát truy cập, luôn có thể trả về tiêu đề Access-Control-Allow-Origin một cách an toàn có giá trị là "*" - CODE-REaD


Bởi vì
$ .ajax ({type: "POST"  - Cuộc gọi TÙY CHỌN 
$ .post ( - Cuộc gọi BÀI ĐĂNG 

cả hai đều khác nhau Postman gọi "POST" đúng cách nhưng khi chúng ta gọi nó là "OPTIONS"

Đối với dịch vụ web c # - webapi 

Vui lòng thêm mã sau vào tệp web.config của bạn trong thẻ <system.webServer>. Điều này sẽ làm việc

<httpProtocol>
    <customHeaders>
        <add name="Access-Control-Allow-Origin" value="*" />
    </customHeaders>
</httpProtocol>

Vui lòng đảm bảo bạn không thực hiện bất kỳ lỗi nào trong cuộc gọi ajax

jQuery

$.ajax({
    url: 'http://mysite.microsoft.sample.xyz.com/api/mycall',
    headers: {
        'Content-Type': 'application/x-www-form-urlencoded'
    },
    type: "POST", /* or type:"GET" or type:"PUT" */
    dataType: "json",
    data: {
    },
    success: function (result) {
        console.log(result);    
    },
    error: function () {
        console.log("error");
    }
});

Angular 4 vấn đề xin vui lòng tham khảo: http://www.hubfly.com/blog/solutions/how-to-fix-angular-4-api-call-issues/

Chú thích: Nếu bạn đang tìm kiếm nội dung tải xuống từ trang web của bên thứ ba sau đó điều này sẽ không giúp bạn. Bạn có thể thử đoạn mã sau chứ không phải JavaScript.

System.Net.WebClient wc = new System.Net.WebClient();
string str = wc.DownloadString("http://mysite.microsoft.sample.xyz.com/api/mycall");

41
2017-12-13 13:02



Cấu hình này đã giải quyết lỗi tương tự trên Wordpress tại Azure Services. Cảm ơn. - Andre Mesquita
Tôi sẽ đề xuất sử dụng giá trị gốc cụ thể để tránh yêu cầu từ miền bên ngoài. Vì vậy, ví dụ thay vì * sử dụng https://www.myotherdomain.com - pechar