Đáp ứng yêu cầu preflight không vượt qua kiểm tra kiểm soát truy cập


457

Tôi đang gặp lỗi này khi sử dụng ngResource để gọi API REST trên Dịch vụ web của Amazon:

XMLHttpRequest không thể tải http://server.apiurl.com:8000/s/login?login=facebook . Trả lờ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 đó, nguồn gốc ' http: // localhost ' không được phép truy cập. Lỗi 405

Dịch vụ:

socialMarkt.factory('loginService', ['$resource', function($resource){    
    var apiAddress = "http://server.apiurl.com:8000/s/login/";
    return $resource(apiAddress, { login:"facebook", access_token: "@access_token" ,facebook_id: "@facebook_id" }, {
                getUser: {method:'POST'}
            });
}]);

Điều khiển:

[...]
loginService.getUser(JSON.stringify(fbObj)),
                function(data){
                    console.log(data);
                },
                function(result) {
                    console.error('Error', result.status);
                }
[...]

Tôi đang sử dụng Chrome và tôi không biết phải làm gì khác để khắc phục sự cố này. Tôi thậm chí đã cấu hình máy chủ để chấp nhận các tiêu đề từ nguồn gốc localhost.


bối rối: bạn đã "cấu hình máy chủ" hay đây là "một api còn lại trên dịch vụ web của amazon"?
dandavis

3
Bạn rõ ràng chưa làm đủ để kích hoạt CORS ở phía máy chủ. Bài mẫu của tiêu đề phản hồi
charlietfl

4
Dù bằng cách nào thì phiếu bầu của bạn đều sai. Ông đang lưu trữ các tập tin của mình trên máy cục bộ của mình. Sẽ không có vấn đề gì với loại conf mà anh ấy làm ở mặt sau. Angular sẽ không cho phép chuyến bay trước này.
E. Maggini

3
Thx cho các ý kiến, nó hoạt động khi tôi đặt trình duyệt chuyển sang bảo mật
Andre Mendes

1
@Andre Nhưng tắt bảo mật chỉ là một cách giải quyết xấu xí mà bạn đang xâm phạm an ninh, không giải quyết được vấn đề của bạn ...
shivi

Câu trả lời:


240

Bạn đang chạy vào các vấn đề CORS.

Có một số cách để khắc phục / giải pháp này.

  1. Tắt CORS. Ví dụ: cách tắt cors trong chrome
  2. Sử dụng plugin cho trình duyệt của bạn
  3. Sử dụng proxy như nginx. ví dụ về cách thiết lập
  4. Đi qua các thiết lập cần thiết cho máy chủ của bạn. Đây là một yếu tố của máy chủ web bạn đã tải trên phiên bản EC2 của bạn (giả sử đây là ý nghĩa của "dịch vụ web Amazon"). Đối với máy chủ cụ thể của bạn, bạn có thể tham khảo trang web CORS cho phép.

Cụ thể hơn, bạn đang cố gắng truy cập api.serverurl.com từ localhost. Đây là định nghĩa chính xác của yêu cầu tên miền chéo.

Bằng cách tắt nó đi để hoàn thành công việc của bạn (OK, bảo mật kém cho bạn nếu bạn truy cập các trang web khác và chỉ cần khởi động) bạn có thể sử dụng proxy khiến trình duyệt của bạn nghĩ rằng tất cả các yêu cầu đến từ máy chủ cục bộ khi thực sự bạn có máy chủ cục bộ mà sau đó gọi máy chủ từ xa.

vì vậy api.serverurl.com có ​​thể trở thành localhost: 8000 / api và nginx cục bộ hoặc proxy khác của bạn sẽ gửi đến đích chính xác.


Bây giờ theo nhu cầu phổ biến, thêm 100% thông tin CORS .... cùng một hương vị tuyệt vời!


Và đối với các downvoters .... bỏ qua CORS là chính xác những gì được hiển thị cho những người chỉ đơn giản là học tập mặt trước. https://codecraft.tv/cifts/angular/http/http-with-promises/


776
bỏ qua một cách rõ ràng về việc thực hiện CORS một cách chính xác
charlietfl

40
Nó rất dễ dàng để bỏ phiếu. Ít dễ dàng để chấp nhận rủi ro cho mình bạn của tôi. Và tất cả những thứ này hoạt động chính xác trong một môi trường dev.
E. Maggini

3
Nó thực sự đã làm việc. Tôi đã thêm cờ để vô hiệu hóa bảo mật Web. Để phát triển là tốt.
Andre Mendes

15
@charlietfl thế nào?
GreenAsJade

3
Cảm ơn bạn đã lưu ngày của tôi. Chỉ sử dụng tùy chọn đầu tiên: C: \ Program Files (x86) \ Google \ Chrome \ Application> chrome.exe --user-data-dir = "C: \ Chrome dev session" --disable-web-security. Từ: stackoverflow.com/questions/3102819/ Lời
Harsimer

169

"Máy chủ API" của tôi là một Ứng dụng PHP vì vậy để giải quyết vấn đề này, tôi đã tìm giải pháp bên dưới để hoạt động:

Đặt các dòng trong index.php

header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: GET, POST, PATCH, PUT, DELETE, OPTIONS');
header('Access-Control-Allow-Headers: Origin, Content-Type, X-Auth-Token');

3
Tôi đồng ý, điều này tốt hơn câu trả lời được chấp nhận mặc dù hãy cẩn thận khi sao chép các dòng này, đảm bảo sửa đổi các phương thức và nguồn gốc.
Amir Savand

11
Nơi để đặt nó trong một dự án Angular 6?
whatthefish

@CodyBugstein và whatthefish đặt trước bất kỳ đầu ra nào
Garet Claborn 30/07/18

Ứng dụng khách của tôi đã ngừng hoạt động khi tôi thêm một tiêu đề chỉ được yêu cầu bởi một số máy chủ. Nếu yêu cầu bao gồm bất kỳ tiêu đề tùy chỉnh, họ sẽ cần phải được liệt kê trong Access-Control-Allow-Headers.
z0r

47

Trong api web AspNetCore, vấn đề này đã được khắc phục bằng cách thêm "Microsoft.AspNetCore.Cors" (phiên bản 1.1.1) và thêm các thay đổi bên dưới trên Startup.cs.

public void ConfigureServices(IServiceCollection services)
{ 
    services.AddCors(options =>
    {
          options.AddPolicy("AllowAllHeaders",
                builder =>
            {
                    builder.AllowAnyOrigin()
                           .AllowAnyHeader()
                           .AllowAnyMethod();
                });
    });
    .
    .
    .
}

public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{


    // Shows UseCors with named policy.
    app.UseCors("AllowAllHeaders");
    .
    .
    .
}

và đưa [EnableCors("AllowAllHeaders")]vào bộ điều khiển.


18
Đây là một câu trả lời tốt nếu bạn muốn xây dựng các lỗ hổng kịch bản chéo trang web! Xin đừng bao giờ làm điều này! Chỉ định tên miền của bạn mà bạn có thể truy cập để tránh các vấn đề bảo mật. CORS là có lý do.
paqogomez

2
Chỉ cần làm cho nó rõ ràng hơn @paqogomez, trong phương thức ConfigureService của bạn: services.AddCors (tùy chọn => {tùy chọn.AddPolicy ("AllowSpecificOrigin", builder => {builder.WithOrigins (" localhost" ). ALLowAnyOrigin (). AllowAnyMethod ();});}); và trong phương thức Cấu hình của bạn: app.UseCors ("AllowSpecificOrigin");
Francisco Tena

28

Có một số hãy cẩn thận khi nói đến CORS. Đầu tiên, nó không cho phép ký tự đại diện *nhưng đừng giữ tôi trên cái này Tôi đã đọc nó ở đâu đó và tôi không thể tìm thấy bài báo bây giờ.

Nếu bạn đang thực hiện các yêu cầu từ một tên miền khác, bạn cần thêm các tiêu đề gốc cho phép.

 Access-Control-Allow-Origin: www.other.com 

Nếu bạn đang làm cho các yêu cầu có ảnh hưởng đến tài nguyên máy chủ như POST / PUT / PATCH, và nếu loại mime khác với những điều sau đây application/x-www-form-urlencoded, multipart/form-datahoặc text/plaintrình duyệt sẽ tự động tạo ra một OPTIONS trước chuyến bay yêu cầu kiểm tra với máy chủ nếu nó sẽ cho phép nó .

Vì vậy, API / máy chủ của bạn cần xử lý các yêu cầu TÙY CHỌN này cho phù hợp, bạn cần phản hồi với access control headersmã trạng thái phản hồi http phù hợp và cần phải có 200.

Các tiêu đề nên là một cái gì đó như thế này, điều chỉnh chúng cho nhu cầu của bạn:

   Access-Control-Allow-Methods: GET, POST, PUT, PATCH, POST, DELETE, OPTIONS
   Access-Control-Allow-Headers: Content-Type
   Access-Control-Max-Age: 86400

Tiêu đề tuổi tối đa rất quan trọng, trong trường hợp của tôi, nó sẽ không hoạt động nếu không có nó, tôi đoán trình duyệt cần thông tin trong bao lâu "quyền truy cập" là hợp lệ.

Ngoài ra, nếu bạn đang thực hiện, ví dụ như một POSTyêu cầu với application/jsonmime từ một tên miền khác, bạn cũng cần thêm tiêu đề cho phép gốc được đề cập trước đó, vì vậy nó sẽ trông như thế này:

   Access-Control-Allow-Origin: www.other.com 
   Access-Control-Allow-Methods: GET, POST, PUT, PATCH, POST, DELETE, OPTIONS
   Access-Control-Allow-Headers: Content-Type
   Access-Control-Max-Age: 86400

Khi chuyến bay trước thành công và nhận được tất cả thông tin cần thiết, yêu cầu thực tế của bạn sẽ được thực hiện.

Nói chung, bất kỳ Access-Controltiêu đề nào được yêu cầu trong yêu cầu ban đầu hoặc trước chuyến bay, nên được đưa ra trong phản hồi để nó hoạt động.

Có một ví dụ điển hình trong các tài liệu MDN ở đây trên liên kết này và bạn cũng nên xem bài đăng SO này


1
Dưới đây là bài viết của Mozilla nói về cách bạn không thể sử dụng ký tự đại diện cho nguồn gốc cors: Liên kết Vì vậy, rõ ràng điều này chỉ áp dụng khi sử dụng thông tin đăng nhập (nếu tôi hiểu chính xác)
Helzgate

Tôi đang sử dụng ký tự đại diện và gửi mã thông báo mang theo để ủy quyền cho yêu cầu và nó hoạt động tốt nên không chắc chắn liên kết tôi cung cấp ở trên có liên quan đến thông tin đăng nhập. Vấn đề của tôi là khi áp dụng chính sách CORS của tôi trong .Net Core tôi đã không thêm .AllowCredentials(). Sau khi thêm .AllowCredentials()mọi thứ làm việc.
Helzgate

15

JavaScript XMLHttpRequestFetch tuân theo chính sách cùng nguồn gốc. Vì vậy, một ứng dụng web sử dụng XMLHttpRequest hoặc Fetch chỉ có thể thực hiện các yêu cầu HTTP đến miền của chính nó.

Nguồn: https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS

Bạn phải gửi tiêu đề Access-Control-Allow-Origin: * HTTP từ phía máy chủ của bạn.

Nếu bạn đang sử dụng Apache làm máy chủ HTTP thì bạn có thể thêm nó vào tệp cấu hình Apache của mình như sau:

<IfModule mod_headers.c>
    Header set Access-Control-Allow-Origin "*"
</IfModule>

Mod_headers được bật theo mặc định trong Apache, tuy nhiên, bạn có thể muốn đảm bảo nó được bật bằng cách chạy:

 a2enmod headers

Tôi có thể tìm thấy tệp cấu hình Apache của mình ở đâu?
Shubham Arya

@ShubhamArya trên linux Debian vị trí mặc định là:/etc/apache2/apache2.conf
Tadej

Tôi có thể tìm thấy nó trong cửa sổ ở đâu?
Shubham Arya

10

Nếu bạn đang viết tiện ích mở rộng chrome

Bạn phải thêm manifest.jsoncác quyền cho (các) tên miền của bạn.

"permissions": [
   "http://example.com/*",
   "https://example.com/*"
]

1
Đồng thời kiểm tra xem bạn có tiền tố www không
Vlas Bashynskyi

8

Nếu bạn đang sử dụng máy chủ IIS một cách tình cờ. bạn có thể đặt các tiêu đề bên dưới trong tùy chọn tiêu đề yêu cầu HTTP.

Access-Control-Allow-Origin:*
Access-Control-Allow-Methods: 'HEAD, GET, POST, PUT, PATCH, DELETE'
Access-Control-Allow-Headers: 'Origin, Content-Type, X-Auth-Token';

với tất cả bài này, nhận được vv, sẽ hoạt động tốt.



5

Trong PHP bạn có thể thêm các tiêu đề:

<?php
header ("Access-Control-Allow-Origin: *");
header ("Access-Control-Expose-Headers: Content-Length, X-JSON");
header ("Access-Control-Allow-Methods: GET, POST, PATCH, PUT, DELETE, OPTIONS");
header ("Access-Control-Allow-Headers: *");
...

cảm ơn, nó đã làm việc cho tôi trong các thử nghiệm và môi trường sản xuất. Ngay cả khi sử dụng https: //
Jose Seie

1
@atiruz Cảm ơn giải pháp. Điều này hoạt động khi tôi thêm dòngheader ("Access-Control-Expose-Headers: Content-Length, X-JSON");
Silambaraan RD

5

Để khắc phục các sự cố yêu cầu nguồn gốc chéo trong ứng dụng Node JS:

npm i cors

Và chỉ cần thêm các dòng dưới đây vào app.js

let cors = require('cors')
app.use(cors())

3
điều này chỉ hoạt động trong các ứng dụng js tốc hành, không phải tất cả các ứng dụng nút
DrCord

3

Trong tệp cấu hình Apache Virtualhost của tôi, tôi đã thêm các dòng sau:

Header always set Access-Control-Allow-Origin "*"
Header always set Access-Control-Allow-Methods "POST, GET, OPTIONS, DELETE, PUT"
Header always set Access-Control-Max-Age "1000"
Header always set Access-Control-Allow-Headers "x-requested-with, Content-Type, origin, authorization, accept, client-security-token"

RewriteEngine On
RewriteCond %{REQUEST_METHOD} OPTIONS
RewriteRule ^(.*)$ $1 [R=200,L]

3

Đối với những người đang sử dụng Proxy tích hợp Lambda với API Gateway . Bạn cần cấu hình chức năng lambda của mình như thể bạn đang gửi yêu cầu của mình trực tiếp đến nó, nghĩa là chức năng sẽ thiết lập tiêu đề phản hồi đúng cách. (Nếu bạn đang sử dụng các chức năng lambda tùy chỉnh, điều này sẽ được xử lý bởi API Gateway.)

//In your lambda's index.handler():
exports.handler = (event, context, callback) => {
     //on success:
     callback(null, {
           statusCode: 200,
           headers: {
                "Access-Control-Allow-Origin" : "*"
           }
     }
}

1
Tôi cũng muốn đồng ý và đề cập đến một vấn đề lớn mà tôi không nghĩ là tài liệu AWS. Giả sử bạn sử dụng cổng API để ủy quyền chức năng lambda của mình và bạn sử dụng một số API trong chức năng lambda đó. Nếu API đó trả về mã thành công không phải là 200 và bạn đã không thêm mã không thành công 200 vào phản hồi phương thức trong cổng API thì bạn sẽ nhận được lỗi và không thấy phản hồi thành công của bạn . Ví dụ cho điều này: Sendgrid và Twilio có 200 mã thành công.
Stephen Tetreault

3

Tôi nghĩ rằng việc vô hiệu hóa CORS khỏi Chrome không phải là cách tốt , bởi vì nếu bạn đang sử dụng nó trong ion, chắc chắn trong Mobile Build, Vấn đề sẽ lại xảy ra.

Vì vậy, tốt hơn để sửa chữa trong phần cuối của bạn.

Trước hết Trong tiêu đề, bạn cần đặt-

  • tiêu đề ('Kiểm soát truy cập-Cho phép-Xuất xứ: *');
  • tiêu đề ('Header set Access-Control-allow-Headers: "Origin, X-Requested-With, Content-Type, Accept"');

Và nếu API hoạt động như GET và POST cả thì cũng Đặt trong tiêu đề của bạn-

if ($ _SERVER ['REQUEST_METHOD'] == 'TÙY CHỌN') {if (isset ($ _ SERVER ['HTTP_ACCESS_CONTROL_REQUEST_METHOD'])) tiêu đề ("Điều khiển truy cập-cho phép-phương thức: GET, POST,"
tiêu đề if (isset ($ _ SERVER ['HTTP_ACCESS_CONTROL_REQUEST_HEADERS'])) ("Access-Control-Allow-Headers:
{$ _SERVER ['HTTP_ACCESS_CONTROL_REQUEST_HEADERS']}"); thoát (0); }


3

Một nguyên nhân rất phổ biến của lỗi này có thể là API máy chủ đã ánh xạ yêu cầu tới phương thức http (ví dụ PUT) và trình khách API đang gọi API bằng phương thức http khác (ví dụ POST hoặc GET)


Tôi đã triển khai CORS đúng cách trong máy chủ của mình nhưng tôi đã quên thêm PUTphương thức
fguillen

3

Nhóm của chúng tôi thỉnh thoảng thấy điều này bằng cách sử dụng Vue, axios và C # WebApi. Thêm một thuộc tính tuyến đường trên điểm cuối bạn đang cố gắng sửa nó cho chúng tôi.

[Route("ControllerName/Endpoint")]
[HttpOptions, HttpPost]
public IHttpActionResult Endpoint() { }

Chúng tôi không thực sự chắc chắn tại sao. Cười lớn. Nếu ai làm cho tôi biết!
w00ngy

1

Tôi đã phải đối mặt với vấn đề này khi máy chủ DNS được đặt thành 8.8.8.8 (của Google). Trên thực tế, vấn đề là ở bộ định tuyến, ứng dụng của tôi đã cố gắng kết nối với máy chủ thông qua google chứ không phải cục bộ (đối với trường hợp cụ thể của tôi). Tôi đã gỡ bỏ 8.8.8.8 và điều này đã giải quyết được vấn đề. Tôi biết rằng vấn đề này được giải quyết bằng cài đặt CORS, nhưng có thể ai đó sẽ gặp rắc rối tương tự như tôi


1

Tôi đang sử dụng AWS sdk để tải lên, sau khi dành thời gian tìm kiếm trực tuyến, tôi tình cờ thấy chủ đề này. nhờ @lsimoneau 45581857 , hóa ra điều tương tự cũng xảy ra. Tôi chỉ cần trỏ Url yêu cầu của mình vào vùng trên thùng của mình bằng cách đính kèm tùy chọn vùng và nó đã hoạt động.

 const s3 = new AWS.S3({
 accessKeyId: config.awsAccessKeyID,
 secretAccessKey: config.awsSecretAccessKey,
 region: 'eu-west-2'  // add region here });

0

Các bản phân phối độc lập của GeoServer bao gồm máy chủ ứng dụng Jetty. Cho phép chia sẻ tài nguyên nguồn gốc chéo (CORS) để cho phép các ứng dụng JavaScript bên ngoài miền của bạn sử dụng GeoServer.

Bỏ ghi chú sau <filter><filter-mapping>từ webapps / geoserver / WEB-INF / web.xml:

<web-app>
  <filter>
      <filter-name>cross-origin</filter-name>
      <filter-class>org.eclipse.jetty.servlets.CrossOriginFilter</filter-class>
  </filter>
  <filter-mapping>
      <filter-name>cross-origin</filter-name>
      <url-pattern>/*</url-pattern>
  </filter-mapping>
</web-app>

Điều đó không thêm phản ứng chống lại tiêu đề phản hồi, vì vậy nó không hoạt động
JollyRoger

1
không sử dụng GeoServer, nhưng clip này đã giúp tôi biết các cài đặt tôi nên sử dụng trên ứng dụng nhận cuộc gọi.
Matt Felzani

0

Thật dễ dàng để giải quyết vấn đề này chỉ với vài bước dễ dàng, không phải lo lắng về bất cứ điều gì. Vui lòng làm theo các bước để giải quyết nó.

  1. mở ( https://www.npmjs.com/package/cors#enables-cors-pre-flight )
  2. đi đến cài đặt và sao chép lệnh npm install cors để cài đặt qua terminal terminal
  3. đi tới Cách sử dụng đơn giản (Kích hoạt tất cả các yêu cầu của CORS) bằng cách cuộn. Sao chép và dán phần khai báo hoàn chỉnh trong dự án của bạn và chạy nó ... điều đó sẽ hoạt động chắc chắn .. sao chép mã nhận xét và dán vào ur app.js hoặc bất kỳ ứng dụng nào khác dự án và thử .. nó sẽ hoạt động. Nó sẽ mở khóa mọi chia sẻ tài nguyên nguồn gốc chéo..chúng tôi có thể chuyển đổi giữa các phục vụ cho việc sử dụng của bạn

1
var express = Yêu cầu ('express') var cors = quiries ('cors') var app = express () app.use (cors ()) app.get ('/ sản phẩm /: id', function (req, res, next) {res.json ({dir: 'Đây là hỗ trợ CORS cho tất cả các nguồn gốc!'})}) app.listen (80, function () {console.log ('Máy chủ web hỗ trợ CORS nghe trên cổng 80' )})
Rahul sah

-1

Một cái gì đó rất dễ bỏ lỡ ...

IN thám hiểm giải pháp, nhấp chuột phải vào dự án api. Trong cửa sổ thuộc tính, đặt 'Xác thực ẩn danh' thành Đã bật !!!


-8

Vô hiệu hóa bảo mật chrome. Tạo một phím tắt chrome nhấp chuột phải -> thuộc tính -> nhắm mục tiêu, dán "C: \ Program Files (x86) \ Google \ Chrome \ Application \ chrome.exe" --disable-web-security --user -data-dir = "c: / chromedev"

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.