API Gateway CORS: không có tiêu đề 'Access-Control-Allow-Origin'


102

Mặc dù CORS đã được thiết lập thông qua API Gateway và Access-Control-Allow-Origintiêu đề được đặt, tôi vẫn gặp lỗi sau khi cố gắng gọi API từ AJAX trong Chrome:

XMLHttpRequest không thể tải http://XXXXX.execute-api.us-west-2.amazonaws.com/beta/YYYYY . Không có tiêu đề 'Access-Control-Allow-Origin' có trên tài nguyên được yêu cầu. Nguồn gốc 'null' do đó không được phép truy cập. Phản hồi có mã trạng thái HTTP 403.

Tôi đã cố gắng NHẬN URL thông qua Postman và nó cho thấy tiêu đề trên đã được chuyển thành công:

Các tiêu đề đã qua

Và từ OPTIONS phản hồi:

Tiêu đề phản hồi

Làm cách nào để gọi API của mình từ trình duyệt mà không hoàn nguyên về JSON-P?


Bạn đã thiết lập nó trên S3 chưa? Nếu vậy, bạn có thể đặt Bucket Policy? Đảm bảo rằng bạn có phương pháp trong chính sách của mình
iSkore

10
Nhóm API Gateway ở đây ... Nếu bạn sử dụng tính năng 'Bật CORS' trong bảng điều khiển, cấu hình phải chính xác. Dự đoán tốt nhất của tôi là bạn không gọi đúng đường dẫn tài nguyên trong API của mình trong JavaScript mà trình duyệt đang thực thi. Nếu bạn cố gắng thực hiện lệnh gọi API tới một phương thức / tài nguyên / giai đoạn không tồn tại, bạn sẽ nhận được mã 403 chung mà không có tiêu đề CORS. Tôi không hiểu làm thế nào trình duyệt có thể bỏ lỡ tiêu đề Access-Control-Allow-Origin nếu bạn đang gọi đúng tài nguyên vì lệnh gọi OPTIONS trong Postman rõ ràng chứa tất cả các tiêu đề CORS phù hợp.
jackko

1
@ RyanG-AWS khách hàng không ký yêu cầu vì API được xác thực bởi tài nguyên mà nó gọi bằng mã thông báo dành riêng cho người dùng, vì vậy thông tin xác thực không phải là một yếu tố. Tôi có thể gọi API bằng cách truy cập trực tiếp vào URL trong trình duyệt và tôi nhận được phản hồi thích hợp.
Tyler

2
@makinbacon: Bạn đã tìm ra giải pháp cho việc này chưa? Tôi đang giải quyết vấn đề tương tự ở đây.
Nirmal

1
Các phương thức và giai đoạn của tôi được tạo tự động bởi Lambda. Tôi đã kích hoạt CORS sau khi thực tế. Các lỗi tương tự như OP. Tôi đã loại bỏ những thứ được tạo tự động, tạo một API và phương thức mới, triển khai sang một giai đoạn mới và nó hoạt động tốt.
bỏng

Câu trả lời:


117

Tôi có một vấn đề tương tự. Tôi đã sử dụng 10hrs để tìm hiểu.

https://serverless.com/framework/docs/providers/aws/events/apigateway/

// handler.js

'use strict';

module.exports.hello = function(event, context, callback) {

const response = {
  statusCode: 200,
  headers: {
    "Access-Control-Allow-Origin" : "*", // Required for CORS support to work
    "Access-Control-Allow-Credentials" : true // Required for cookies, authorization headers with HTTPS 
  },
  body: JSON.stringify({ "message": "Hello World!" })
};

callback(null, response);
};

Đã khắc phục sự cố tôi đang gặp phải. Cảm ơn về câu trả lời của bạn!
Eric Brown,

Tôi không sử dụng serverless, nhưng điều này đã giải quyết được vấn đề của tôi. Đoán rằng bạn cần chuyển các tiêu đề đó ra khỏi nguồn thực tế.
Costa

2
FYI, có một vấn đề với ví dụ được trình bày ở đây. Nếu bạn có "Access-Control-Allow-Credentials": true, bạn không thể có ký tự đại diện * cho Access-Control-Allow-Origin. Quy tắc này được thực thi bởi trình duyệt. Xem ở đâyở đây
Kevin

1
Điều này không hoạt động, Một lần nữa hiển thị lỗi tương tự Trường tiêu đề yêu cầu truy cập-kiểm soát-allow-thông tin đăng nhập không được phép bởi Access-Control-Allow-Headers trong phản hồi trước khi bắt đầu.
mitesh7172

1
Đối với bất kỳ ai tò mò, đây là tài liệu chính thức đề cập đến vấn đề này: docs.aws.amazon.com/apigateway/latest/developerguide/… > Đối với tích hợp proxy Lambda hoặc HTTP, bạn vẫn có thể thiết lập tiêu đề phản hồi TÙY CHỌN trong API Gateway. Tuy nhiên, bạn phải dựa vào> back end để trả về các tiêu đề Access-Control-Allow-Origin vì phản hồi tích hợp> bị tắt đối với tích hợp proxy.
Leonid Usov

104

Nếu bất kỳ ai khác vẫn gặp phải vấn đề này - tôi đã có thể tìm ra nguyên nhân gốc rễ trong ứng dụng của mình.

Nếu bạn đang chạy API-Gateway với Ủy quyền tùy chỉnh - API-Gateway sẽ gửi lại 401 hoặc 403 trước khi nó thực sự truy cập vào máy chủ của bạn. Theo mặc định - API-Gateway KHÔNG được định cấu hình cho CORS khi trả về 4xx từ trình ủy quyền tùy chỉnh.

Ngoài ra - nếu bạn tình cờ nhận được mã trạng thái của 0hoặc 1từ một yêu cầu chạy qua API Gateway, đây có thể là vấn đề của bạn.

Để khắc phục - trong cấu hình API Gateway - hãy chuyển đến "Gateway Responses", mở rộng "Default 4XX" và thêm tiêu đề cấu hình CORS vào đó. I E

Access-Control-Allow-Origin: '*'

Đảm bảo triển khai lại cổng của bạn - và thì đấy!


7
Tôi mến bạn. đã nghiêm túc làm việc này trong hai ngày.
efong5

4
Đối với những người muốn làm điều này với AWS CLI, hãy sử dụng:aws apigateway update-gateway-response --rest-api-id "XXXXXXXXX" --response-type "DEFAULT_4XX" --patch-operations op="add",path="/responseParameters/gatewayresponse.header.Access-Control-Allow-Origin",value='"'"'*'"'"'
Sẽ

1
Tôi không sử dụng Ủy quyền tùy chỉnh và vẫn cần điều này vì yêu cầu của tôi có JSON không hợp lệ - cảm ơn bạn!
Force Hero

9
lưu ý cho bản thân - đừng quên triển khai API sau đó :)
danieln

2
Thật kỳ lạ, điều này có hiệu quả với tôi, nhưng tôi không phải triển khai lại. Tôi đã thử triển khai lại trước đó. Không chắc tại sao nó làm việc cho tôi.
Michael

19

1) Tôi cần thực hiện tương tự như @riseres và một số thay đổi khác. Đây là tiêu đề phản hồi của tôi:

headers: {
            'Access-Control-Allow-Origin' : '*',
            'Access-Control-Allow-Headers':'Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token',
            'Access-Control-Allow-Credentials' : true,
            'Content-Type': 'application/json'
        }

2 và

Theo tài liệu này:

http://docs.aws.amazon.com/apigateway/latest/developerguide/how-to-cors.html

Khi bạn sử dụng proxy cho các hàm lambda trên cấu hình API Gateway, các phương thức post hoặc get không có tiêu đề được thêm vào, chỉ có các tùy chọn. Bạn phải thực hiện thủ công trong phản hồi (máy chủ hoặc phản hồi lambda).

3) Và

Bên cạnh đó, tôi cần tắt tùy chọn 'Yêu cầu khóa API' trong phương pháp đăng cổng API của mình.


5
Đúng vậy, tôi nghĩ rằng điều tinh tế mà nhiều người trong chúng ta bỏ lỡ ban đầu là khi bạn định cấu hình tích hợp API Gateway cho hàm Lambda với "Sử dụng Lambda Proxy Integration", thì bạn phải làm như bạn và những người khác đang nêu và đảm bảo các tiêu đề được thêm vào theo chương trình trong phản hồi của lambda của bạn. Nội dung tự động tạo ra được tạo bằng cách "Bật CORS" trên Cổng API và nó tạo ra một trình phản hồi TÙY CHỌN là rất tốt nhưng không giúp bạn hoàn thành việc đó nếu bạn đặt "Sử dụng tích hợp Lambda Proxy" trong Yêu cầu tích hợp trong API Cổng vào.

1
Điều này có hiệu quả với tôi ... sau khi đọc đúng hướng dẫn sử dụng: Quan trọng Khi áp dụng các hướng dẫn trên cho BẤT KỲ phương pháp nào trong tích hợp proxy, mọi tiêu đề CORS hiện hành sẽ không được đặt. Thay vào đó, chương trình phụ trợ của bạn phải trả lại các tiêu đề CORS hiện hành, chẳng hạn như Access-Control-Allow-Origin. docs.aws.amazon.com/apigateway/latest/developerguide/…
BennyHilarious

14

Nếu bạn đã thử mọi thứ liên quan đến vấn đề này mà không có kết quả, bạn sẽ kết thúc nơi tôi đã làm. Hóa ra, các hướng dẫn thiết lập CORS hiện có của Amazon hoạt động tốt ... chỉ cần đảm bảo bạn nhớ triển khai lại ! Trình hướng dẫn chỉnh sửa CORS, ngay cả với tất cả các dấu kiểm màu xanh lá cây nhỏ xinh, không thực hiện cập nhật trực tiếp cho API của bạn. Có lẽ rõ ràng, nhưng nó làm tôi bối rối trong nửa ngày.

nhập mô tả hình ảnh ở đây


Đây chính là nó. Theo nghĩa đen, làm việc này trong hai ngày. Không chắc chắn logic trong ít nhất không nhắc triển khai lại sau khi bạn chỉnh sửa cổng vào.
Chris Christensen

@ChrisChristensen vui mừng bạn đã nhận nó tìm ra - luôn luôn có điều gì đó để giảm nhưng vẫn vô cùng đánh bại về những vấn đề như thế này
lase

Đây là câu trả lời có giá trị vào năm 2020. Cảm ơn
Rahul Khanna

RE-DEPLOY RE-DPLOY RE-DEPLOY
Surjith SM

11

Mẫu của tôi đang hoạt động: Tôi vừa chèn 'Access-Control-Allow-Origin': '*', bên trong tiêu đề: {} trong hàm nodejs Lambda đã tạo. Tôi không thực hiện thay đổi nào đối với lớp API do Lambda tạo.

Đây là NodeJS của tôi:

'use strict';
const doc = require('dynamodb-doc');
const dynamo = new doc.DynamoDB();
exports.handler = ( event, context, callback ) => {
    const done = ( err, res ) => callback( null, {
        statusCode: err ? '400' : '200',
        body: err ? err.message : JSON.stringify(res),
        headers:{ 'Access-Control-Allow-Origin' : '*' },
    });
    switch( event.httpMethod ) {
        ...
    }
};

Đây là cuộc gọi AJAX của tôi

$.ajax({
    url: 'https://x.execute-api.x-x-x.amazonaws.com/prod/fnXx?TableName=x',
    type: 'GET',
    beforeSend: function(){ $( '#loader' ).show();},
    success: function( res ) { alert( JSON.stringify(res) ); },
    error:function(e){ alert('Lambda returned error\n\n' + e.responseText); },
    complete:function(){ $('#loader').hide(); }
});

Tôi thấy nhiều tài liệu của Amazon đã lỗi thời, ngay cả với đoạn đường dẫn "../latest/ ..". Sau khi loại bỏ mọi thứ khoảng một tuần trước, nút CORS đột nhiên thông báo hoạt động bình thường. API đã tự động tạo phương thức "BẤT KỲ" và nút CORS tự động tạo phương thức "TÙY CHỌN" - Tôi không thêm gì vào API. "GET" ở trên hoạt động và kể từ đó tôi đã thêm ajax "POST" cũng hoạt động mà tôi không cần chạm vào API.
MannyC

Tôi đã dành gần hai giờ để cố gắng tìm cách thêm Access-Control-Allow-Origin vào phản hồi phương thức bằng bảng điều khiển AWS, nhưng đây cũng là điều duy nhất phù hợp với tôi.
Shn_Android_Dev

8

Đối với nhân viên Google:

Đây là lý do tại sao:

  • Yêu cầu đơn giản hoặc GET/ POSTkhông có cookie không kích hoạt preflight
  • Khi bạn định cấu hình CORS cho một đường dẫn, API Gateway sẽ chỉ tạo một OPTIONSphương thức cho đường dẫn đó, sau đó gửi Allow-Origintiêu đề bằng cách sử dụng phản hồi giả khi người dùng gọi OPTIONS, nhưng GET/ POSTsẽ không Allow-Origintự động nhận
  • Nếu bạn cố gắng gửi các yêu cầu đơn giản khi bật chế độ CORS, bạn sẽ gặp lỗi vì phản hồi đó không có Allow-Origintiêu đề
  • Bạn có thể tuân thủ thực tiễn tốt nhất, các yêu cầu đơn giản không có nghĩa là gửi phản hồi cho người dùng, gửi xác thực / cookie cùng với các yêu cầu của bạn để làm cho nó "không đơn giản" và preflight sẽ kích hoạt
  • Tuy nhiên, bạn sẽ phải tự mình gửi tiêu đề CORS cho yêu cầu sau OPTIONS

Tóm lại:

  • OPTIONSAPI Gateway chỉ vô hại sẽ được tạo tự động
  • OPTIONSchỉ được sử dụng bởi trình duyệt như một biện pháp thận trọng để kiểm tra khả năng xuất hiện CORS trên đường dẫn
  • Việc CORS có được chấp nhận hay không phụ thuộc vào phương pháp thực tế, ví dụ GET/POST
  • Bạn phải gửi thủ công các tiêu đề thích hợp trong phản hồi của mình

5

Tôi vừa thêm tiêu đề vào phản hồi hàm lambda của mình và nó hoạt động như một sự quyến rũ

exports.handler = async (event) => {
    const response = {
        statusCode: 200,
        body: JSON.stringify('Hey it works'),
        headers:{ 'Access-Control-Allow-Origin' : '*' }
    };
    return response;
};

4

Tôi đã tìm thấy một giải pháp đơn giản trong

API Gateway> Chọn điểm cuối API của bạn> Chọn phương pháp (trong trường hợp của tôi, đó là BÀI ĐĂNG)

Bây giờ có một trình đơn thả xuống ACTIONS> Enable CORS .. hãy chọn nó.

Bây giờ hãy chọn lại ACTIONS trong trình đơn thả xuống> Triển khai API (triển khai lại nó)

nhập mô tả hình ảnh ở đây

Nó đã làm việc !


Tại sao câu trả lời này bị bỏ phiếu thấp nhưng lại có những câu trả lời khác tương tự bên dưới?
Dinesh Kumar

Đối với lệnh gọi cổng API dựa trên AWS, giải pháp này hoạt động
ewalel

3

Tôi bắt đầu làm việc sau khi tôi nhận ra rằng tác giả lambda đang bị lỗi và vì một số lý do không xác định đã được dịch thành lỗi CORS. Một bản sửa lỗi đơn giản cho tác giả của tôi (và một số bài kiểm tra tác giả mà tôi lẽ ra phải thêm vào ngay từ đầu) và nó đã hoạt động. Đối với tôi, hành động API Gateway 'Bật CORS' là bắt buộc. Điều này đã thêm tất cả các tiêu đề và các cài đặt khác mà tôi cần trong API của mình.


và triển khai lại! :)
Robin C Samuel

3

Đối với tôi, câu trả lời CUỐI CÙNG CÓ TÁC DỤNG, là nhận xét của James Shapiro từ câu trả lời của Alex R (được ủng hộ nhiều thứ hai). Tôi đã gặp phải vấn đề API Gateway này ngay từ đầu, bằng cách cố gắng lấy một trang web tĩnh được lưu trữ trong S3 để sử dụng lambda để xử lý trang liên hệ với chúng tôi và gửi email. Chỉ cần kiểm tra [] Mặc định 4XX đã khắc phục được thông báo lỗi.

nhập mô tả hình ảnh ở đây


Bạn tìm thấy menu này ở đâu? Tôi không thấy nó ở đâu cả.
Nick H

@NickH hãy xem bức ảnh từ Ravi Ram. Trong "Tác vụ", sẽ có một mục được gọi là "Bật CORS" và khi bạn chọn mục đó, menu sẽ hiển thị.
Jason

2

Sau khi thay đổi chức năng hoặc mã của bạn Làm theo hai bước sau.

Đầu tiên Kích hoạt CORS Sau đó Triển khai API mọi lúc.


Cảm ơn vì điều đó. Không nhận thấy "Bật CORS" trong tài nguyên. Làm tôi mất trí.
Shlomi Bazel

2

Triển khai mã sau khi bật CORS cho cả hai POSTOPTIONShiệu quả với tôi.


1
Cảm ơn sự đóng góp của bạn, tuy nhiên, bạn có thể giải thích tại sao nó có tác dụng với bạn không? Tôi mời bạn đọc hướng dẫn này để cải thiện câu trả lời của bạn: "Cách tôi viết một câu trả lời hay" tại đây: stackoverflow.com/help/how-to-answer
Guillaume Raymond

1

Tôi đang chạy aws-serverless-expressvà trong trường hợp của tôi cần phải chỉnh sửa simple-proxy-api.yaml.

Trước khi CORS được định cấu hình https://example.com, tôi chỉ cần hoán đổi tên trang web của mình và triển khai lại qua npm run setup, và nó cập nhật lambda / stack hiện có của tôi.

#...
/:
#...
method.response.header.Access-Control-Allow-Origin: "'https://example.com'"
#...
/{proxy+}:
method.response.header.Access-Control-Allow-Origin: "'https://example.com'"
#...

1

Trong trường hợp của tôi, vì tôi đang sử dụng AWS_IAM làm phương thức Cấp phép cho API Gateway, tôi cần cấp quyền cho vai trò IAM của mình để đạt được điểm cuối.


2
Tôi rất vui vì tôi đã để lại bình luận này. Điều này cứ xảy ra với tôi: D.
CamHart

Tôi thích tìm giải pháp của riêng mình cho một vấn đề tái diễn trong tương lai.
Zac Grierson

0

Một nguyên nhân gốc rễ khác của vấn đề này có thể là sự khác biệt giữa HTTP / 1.1 và HTTP / 2.

Dấu hiệu: Một số người dùng, không phải tất cả, đã báo cáo gặp lỗi CORS khi sử dụng Phần mềm của chúng tôi.

Vấn đề: Các Access-Control-Allow-Origintiêu đề đã mất tích đôi khi .

Bối cảnh: Chúng tôi đã có một Lambda tại chỗ, chuyên xử lý OPTIONSyêu cầu và trả lời với các tiêu đề CORS tương ứng, chẳng hạn như Access-Control-Allow-Originkhớp với một danh sách trắng Origin.

Giải pháp: API Gateway dường như chuyển đổi tất cả các tiêu đề thành chữ thường cho các cuộc gọi HTTP / 2, nhưng vẫn duy trì cách viết hoa cho HTTP / 1.1. Điều này khiến việc truy cập event.headers.originkhông thành công.

Kiểm tra xem bạn có đang gặp sự cố này không:

Giả sử API của bạn được đặt tại https://api.example.comvà giao diện người dùng của bạn ở https://www.example.com. Sử dụng CURL, đưa ra yêu cầu bằng HTTP / 2:

curl -v -X OPTIONS -H 'Origin: https://www.example.com' https://api.example.com

Đầu ra phản hồi phải bao gồm tiêu đề:

< Access-Control-Allow-Origin: https://www.example.com

Lặp lại bước tương tự bằng cách sử dụng HTTP / 1.1 (hoặc với Origintiêu đề chữ thường ):

curl -v -X OPTIONS --http1.1 -H 'Origin: https://www.example.com' https://api.example.com

Nếu Access-Control-Allow-Origintiêu đề bị thiếu, bạn có thể muốn kiểm tra phân biệt chữ hoa chữ thường khi đọc Origintiêu đề.


0

Ngoài nhận xét của những người khác, điều cần chú ý là trạng thái được trả về từ tích hợp cơ bản của bạn và liệu tiêu đề Access-Control-Allow-Origin có được trả về cho trạng thái đó hay không.

Thực hiện điều 'Bật CORS' chỉ thiết lập trạng thái 200. Nếu bạn có những người khác trên điểm cuối, ví dụ: 4xx và 5xx, bạn cần tự thêm tiêu đề.


-2

Trong trường hợp của tôi, tôi chỉ đơn giản là viết sai URL yêu cầu tìm nạp. Bật serverless.yml, bạn đặt corsthành true:

register-downloadable-client:
    handler: fetch-downloadable-client-data/register.register
    events:
      - http:
          path: register-downloadable-client
          method: post
          integration: lambda
          cors: true
          stage: ${self:custom.stage}

và sau đó trên trình xử lý lambda, bạn gửi tiêu đề, nhưng nếu bạn thực hiện sai yêu cầu tìm nạp trên giao diện người dùng, bạn sẽ không nhận được tiêu đề đó trong phản hồi và bạn sẽ gặp lỗi này. Vì vậy, hãy kiểm tra kỹ URL yêu cầu của bạn ở mặt trước.


-3

Trong Python, bạn có thể làm điều đó như trong đoạn mã dưới đây:

{ "statusCode" : 200,
'headers': 
    {'Content-Type': 'application/json',
    'Access-Control-Allow-Origin': "*"
     },
"body": json.dumps(
    {
    "temperature" : tempArray,
    "time": timeArray
    })
 }
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.