Nguồn gốc không được phép bởi Access-Control-Cho phép-Origin


337

Tôi đang tạo một Ajax.requestmáy chủ PHP từ xa trong ứng dụng Sencha Touch 2 (được gói trong PhoneGap ).

Phản hồi từ máy chủ như sau:

XMLHttpRequest không thể tải http://nqatalog.negroesquisso.pt/login.php . Nguồn gốc http://localhost:8888không được phép bởi Access-Control-Cho phép-Origin.

Làm thế nào tôi có thể khắc phục vấn đề này?


19
trong khi sử dụng jQuery, thiết lập dataType: 'jsonp',hiện các trick
amit

11
bằng cách đó không phải là phản hồi từ máy chủ. Để chính xác rằng lỗi được phát hành ở phía khách hàng.
matteo

2
Thủ thuật jsonp có lẽ không còn hoạt động nữa, fyi: stackoverflow.com/questions/12216208/NH
drewww

7
Lưu ý, vì tôi chỉ lãng phí nửa ngày để theo đuổi lỗi này - Nếu tập lệnh phía máy chủ không thành công với lỗi máy chủ nội bộ, trình duyệt có thể hiểu nó như thể yêu cầu không được phép do Access-Control-Allow-Originvà báo cáo đây là lỗi.
troelskn

1
@troelskn Bạn vừa cứu mạng tôi. Tôi đã tìm kiếm một số lỗi CORS kể từ 3 ngày và đó chỉ là một sự cố cấu hình Spring nhỏ gây ra 500, tôi đã giải quyết trong 5 phút sau khi đọc bình luận của bạn và tôi thực sự tìm kiếm nó. Cảm ơn bạn!
Alexis Dufrenoy

Câu trả lời:


378

Tôi đã viết một bài viết về vấn đề này một thời gian trước, CrossAX AJAX .

Cách dễ nhất để xử lý việc này nếu bạn có quyền kiểm soát máy chủ phản hồi là thêm tiêu đề phản hồi cho:

Access-Control-Allow-Origin: *

Điều này sẽ cho phép Ajax tên miền chéo . Trong PHP, bạn sẽ muốn sửa đổi phản hồi như vậy:

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

Bạn chỉ có thể đặt Header set Access-Control-Allow-Origin *cài đặt trong tệp cấu hình Apache hoặc tệp htaccess.

Cần lưu ý rằng điều này vô hiệu hóa hiệu quả bảo vệ CORS, rất có thể khiến người dùng của bạn tấn công . Nếu bạn không biết rằng bạn đặc biệt cần sử dụng ký tự đại diện, bạn không nên sử dụng nó và thay vào đó bạn nên đưa danh sách trắng vào tên miền cụ thể của mình:

<?php header('Access-Control-Allow-Origin: http://example.com') ?>

4
Tôi sẽ liên hệ với nhà cung cấp máy chủ của tôi. Cảm ơn
Ricardo

8
Có bất kỳ mối quan tâm an ninh với điều này? Ví dụ, câu trả lời này cho biết "JavaScript bị giới hạn bởi" chính sách nguồn gốc giống nhau "vì lý do bảo mật, ví dụ: tập lệnh độc hại không thể liên lạc với máy chủ từ xa và gửi dữ liệu nhạy cảm từ trang web của bạn."
JohnK

4
Thật tuyệt vời, tôi vừa đặt cái này vào tệp máy chủ node.js của mình: answer.writeHead (200, {'Content-Type': contentType, 'Access-Control-Allow-Origin': '*'}); Va no đa hoạt động. Cảm ơn!
vbullinger

25
JohnK, vâng, ký tự đại diện sẽ cho phép bất kỳ tên miền nào gửi yêu cầu đến máy chủ của bạn. Tôi khuyên bạn nên thay thế dấu hoa thị bằng một tên miền cụ thể mà bạn sẽ chạy tập lệnh trên.
Nick

7
Thật thú vị khi bạn nghĩ rằng ký tự đại diện thậm chí không nên được đề xuất @jfrej. Tất cả phụ thuộc vào mục tiêu của bạn. Ví dụ: lý do chúng tôi sử dụng ký tự đại diện (và đăng câu trả lời này) là vì chúng tôi đang xây dựng một tiện ích nhúng cho bất kỳ trang web nào sử dụng.
Matt Mombrea

63

Nếu bạn không có quyền kiểm soát máy chủ, bạn chỉ cần thêm đối số này vào trình khởi chạy Chrome của mình:--disable-web-security .

Lưu ý rằng tôi sẽ không sử dụng điều này cho "lướt web" bình thường. Để tham khảo, hãy xem bài đăng này: Vô hiệu hóa chính sách xuất xứ tương tự trong Chrome .

Một bạn sử dụng Phonegap để thực sự xây dựng ứng dụng và tải nó lên thiết bị, đây sẽ không phải là vấn đề.


Cảm ơn. Nhưng ứng dụng của tôi đang chạy trên thiết bị di động, tôi không thể chuyển đối số cho trình bao bọc webview của mình.
Ricardo

Bạn không kiểm tra ứng dụng của bạn trong trình duyệt trước? Làm thế nào để bạn gỡ lỗi?
Travis Webb

Có, tôi gỡ lỗi trong trình duyệt Chrome, nhưng ứng dụng sẽ không chạy trên chrome. Nó sẽ có trên điện thoại webgap phù thủy tôi không thể kiểm soát.
Ricardo

4
đọc câu trả lời: bạn chỉ cần thêm đối số này vào trình khởi chạy Chrome của mình . Không có cài đặt nào cho điều này trong Chrome
Travis Webb

2
Tất nhiên là không an toàn. OP đang yêu cầu một cách xung quanh các biện pháp an ninh.
Travis Webb

42

Nếu bạn đang sử dụng Apache, chỉ cần thêm:

<ifModule mod_headers.c>
    Header set Access-Control-Allow-Origin: *
</ifModule>

trong cấu hình của bạn. Điều này sẽ khiến tất cả các phản hồi từ máy chủ web của bạn có thể truy cập được từ bất kỳ trang web nào khác trên internet. Nếu bạn dự định chỉ cho phép các dịch vụ trên máy chủ của mình được sử dụng bởi một máy chủ cụ thể, bạn có thể thay thế *bằng URL của máy chủ gốc:

Header set Access-Control-Allow-Origin: http://my.origin.host

3
Và đừng quên tải mô-đun: tiêu đề a2enmod
Walery Strauch

Làm thế nào để tải mô-đun: tiêu đề a2enmod?
Ayesha

18

Nếu bạn có ứng dụng ASP.NET / ASP.NET MVC , bạn có thể bao gồm tiêu đề này thông qua tệp Web.config:

<system.webServer>
  ...

    <httpProtocol>
        <customHeaders>
            <!-- Enable Cross Domain AJAX calls -->
            <remove name="Access-Control-Allow-Origin" />
            <add name="Access-Control-Allow-Origin" value="*" />
        </customHeaders>
    </httpProtocol>
</system.webServer>

2
.NET MVC Mọi người, XEM tại đây! Tôi thực sự sẽ gõ một giải pháp và chỉ ra câu trả lời này trên blog của mình để mọi người có thể tìm thấy nó dễ dàng hơn. Không có gì tệ hơn là cố gắng vượt qua rào cản .NET / MVC và không tìm thấy gì ngoài các giải pháp PHP / jQuery. Cảm ơn @ Caio-Proiete
ottoflux

1
Làm thế nào điều này không làm việc cho tôi? Tôi đang sử dụng Chrome và đang cố truy cập trang tài chính yahoo từ localhost của tôi.
newman

1
cảm ơn nó đã làm việc cho tôi Tôi đã thêm vào dự án mã phía máy chủ (web.config).
ethem 19/03/2015

15

Đây là câu hỏi / câu trả lời đầu tiên xuất hiện cho tôi khi cố gắng giải quyết vấn đề tương tự bằng cách sử dụng ASP.NET MVC làm nguồn dữ liệu của tôi. Tôi nhận ra điều này không giải quyết được câu hỏi PHP , nhưng nó có liên quan đủ để có giá trị.

Tôi đang sử dụng ASP.NET MVC. Bài viết từ Greg Brant làm việc cho tôi. Cuối cùng, bạn tạo một thuộc tính [HttpHeaderAttribute("Access-Control-Allow-Origin", "*")], mà bạn có thể thêm vào các hành động của bộ điều khiển.

Ví dụ:

public class HttpHeaderAttribute : ActionFilterAttribute
{
    public string Name { get; set; }
    public string Value { get; set; }
    public HttpHeaderAttribute(string name, string value)
    {
        Name = name;
        Value = value;
    }

    public override void OnResultExecuted(ResultExecutedContext filterContext)
    {
        filterContext.HttpContext.Response.AppendHeader(Name, Value);
        base.OnResultExecuted(filterContext);
    }
}

Và sau đó sử dụng nó với:

[HttpHeaderAttribute("Access-Control-Allow-Origin", "*")]
public ActionResult MyVeryAvailableAction(string id)
{
    return Json( "Some public result" );
}

1
WebApi 2 đã được tích hợp sẵn ngay bây giờ. asp.net/web-api/overview/security/ khăn
Matt Frear

10

Vì Matt Mombrea là chính xác cho phía máy chủ, bạn có thể gặp phải một vấn đề khác đó là từ chối danh sách trắng.

Bạn phải cấu hình phonegap.plist của bạn. (Tôi đang sử dụng phiên bản cũ của phonegap)

Đối với cordova, có thể có một số thay đổi trong cách đặt tên và thư mục. Nhưng các bước nên chủ yếu giống nhau.

Đầu tiên chọn Tệp hỗ trợ> PhoneGap.plist

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

sau đó trong "Bên ngoài"

Thêm một mục, với giá trị có lẽ là " http://nqatalog.negroesquisso.pt " Tôi chỉ sử dụng * cho mục đích gỡ lỗi.

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


8

Điều này có thể hữu ích cho bất kỳ ai cần ngoại lệ cho cả hai phiên bản 'www' và 'không phải www' của người giới thiệu:

 $referrer = $_SERVER['HTTP_REFERER'];
 $parts = parse_url($referrer);
 $domain = $parts['host'];

 if($domain == 'google.com')
 {
         header('Access-Control-Allow-Origin: http://google.com');
 }
 else if($domain == 'www.google.com')
 {
         header('Access-Control-Allow-Origin: http://www.google.com');
 }

Chỉ cho tôi đi đúng hướng trong việc giải quyết lỗi ACAO với phương vị. Trong khi tôi đã thêm tên máy chủ được cho phép của googledrive. URL được sử dụng cần phải được googledrive KHÔNG googledrive
Kildareflare

7

Tôi sẽ cung cấp cho bạn một giải pháp đơn giản cho việc này. Trong trường hợp của tôi, tôi không có quyền truy cập vào một máy chủ. Trong trường hợp đó, bạn có thể thay đổi chính sách bảo mật trong trình duyệt Google Chrome của mình để cho phép Kiểm soát truy cập-Cho phép-Xuất xứ. Điều này rất đơn giản:

  1. Tạo lối tắt trình duyệt Chrome
  2. Nhấp chuột phải vào biểu tượng cắt ngắn -> Thuộc tính -> Phím tắt -> Mục tiêu

Dán đơn giản trong "C:\Program Files\Google\Chrome\Application\chrome.exe" --allow-file-access-from-files --disable-web-security.

Vị trí có thể khác nhau. Bây giờ hãy mở Chrome bằng cách nhấp vào phím tắt đó.


7

Tôi đã gặp phải điều này một vài lần khi làm việc với các API khác nhau. Thường thì cách khắc phục nhanh là thêm "& gọi lại =?" đến cuối chuỗi. Đôi khi, ký hiệu và phải là mã ký tự và đôi khi là "?": "? Callback =?" (xem Sử dụng API của Dự báo.io với jQuery )


6

Nếu bạn đang viết một mở rộng Chrome và nhận được lỗi này, sau đó hãy chắc chắn bạn đã thêm URL cơ sở của API để bạn manifest.json's cho phép khối , ví dụ:

"permissions": [
    "https://itunes.apple.com/"
]

6

Điều này là do chính sách cùng nguồn gốc . Xem thêm tại Mozilla Developer Network hoặc Wikipedia .

Về cơ bản, trong ví dụ của bạn, bạn chỉ cần tải http://nqatalog.negroesquisso.pt/login.phptrang từ nqatalog.negroesquisso.ptchứ không phải localhost.


1
Nhưng tôi cần tải dịch vụ web từ thiết bị di động, tôi sẽ bỏ qua việc này chứ?
Ricardo

Vâng, bạn cần thực hiện một số thay đổi phía máy chủ hoặc sử dụng JSONP en.wikipedia.org/wiki/JSONP
antyrat

6

nếu bạn đang bị apache, chỉ cần thêm tệp .htaccess vào thư mục của bạn với nội dung này:

Header set Access-Control-Allow-Origin: *

Header set Access-Control-Allow-Headers: content-type

Header set Access-Control-Allow-Methods: *

5

Trong Ruby on Rails , bạn có thể thực hiện trong bộ điều khiển:

headers['Access-Control-Allow-Origin'] = '*'

Bộ điều khiển nào bạn đặt cái này vào nếu nó là một cuộc gọi ajax? Tôi có thể xem thêm ngữ cảnh mã không?
Rigdonmr

5

Bạn có thể làm cho nó hoạt động mà không cần sửa đổi máy chủ bằng cách tạo broswer bao gồm tiêu đề Access-Control-Allow-Origin: * trong các phản hồi của HTTP TÙY CHỌN.

Trong Chrome, sử dụng tiện ích mở rộng này . Nếu bạn đang trên Mozilla, hãy kiểm tra câu trả lời này .


5

Nếu bạn nhận được điều này trong Angular.js, thì hãy đảm bảo bạn thoát khỏi số cổng như thế này:

var Project = $resource(
    'http://localhost\\:5648/api/...', {'a':'b'}, {
        update: { method: 'PUT' }
    }
);

Xem ở đây để biết thêm về nó.


4

Chúng tôi cũng có vấn đề tương tự với ứng dụng phonegap được thử nghiệm trong chrome. Một máy windows chúng tôi sử dụng tập tin dưới đây hàng ngày trước khi mở Chrome. Hãy nhớ trước khi chạy, bạn cần xóa tất cả chrome khỏi trình quản lý tác vụ hoặc bạn có thể chọn chrome để không chạy trong nền.

BATCH: (sử dụng cmd)

cd D:\Program Files (x86)\Google\Chrome\Application\chrome.exe --disable-web-security

1

Ở Ruby Sinatra

response['Access-Control-Allow-Origin'] = '*' 

cho mọi người hoặc

response['Access-Control-Allow-Origin'] = 'http://yourdomain.name' 

0

Khi bạn nhận được yêu cầu, bạn có thể

var origin = (req.headers.origin || "*");

hơn là khi bạn phải trả lời đi với một cái gì đó như thế:

res.writeHead(
    206,
    {
        'Access-Control-Allow-Credentials': true,
        'Access-Control-Allow-Origin': origin,
    }
);
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.