Происхождение не разрешено Access-Control-Allow-Origin

337

Я делаю Ajax.requestна удаленный сервер PHP в приложении Sencha Touch 2 (завернутый в PhoneGap ).

Ответ от сервера следующий:

XMLHttpRequest не может загрузить http://nqatalog.negroesquisso.pt/login.php . Происхождение http://localhost:8888не разрешено Access-Control-Allow-Origin.

Как я могу решить эту проблему?

Рикардо
источник
19
при использовании jQuery настройка dataType: 'jsonp',делает свое дело
amit
11
Кстати, это не ответ от сервера. Чтобы быть точным, эта ошибка выдается на стороне клиента.
Маттео
2
Уловка jsonp, вероятно, больше не работает, fyi: stackoverflow.com/questions/12216208/…
drewww
7
Обратите внимание, поскольку я просто потратил полдня на погоню за этой ошибкой. Если сценарий на стороне сервера завершается с ошибкой внутреннего сервера, браузер может интерпретировать его, как если бы запрос не был разрешен из-за этого, Access-Control-Allow-Originи сообщить об этом как об ошибке.
troelskn
1
@troelskn Ты только что спас мне жизнь. Я искал какую-то ошибку CORS с 3-х дней, и это была просто небольшая проблема конфигурации Spring, вызывающая 500, которую я решил за 5 минут, как только прочитал ваш комментарий и действительно его искал. Спасибо!
Алексис Дафреной

Ответы:

378

Недавно я написал статью по этому вопросу, Cross Domain AJAX .

Самый простой способ справиться с этим, если у вас есть контроль над отвечающим сервером, это добавить заголовок ответа для:

Access-Control-Allow-Origin: *

Это позволит междоменный Ajax . В PHP вы захотите изменить ответ следующим образом:

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

Вы можете просто поместить Header set Access-Control-Allow-Origin *настройку в конфигурацию Apache или в файл htaccess.

Следует отметить, что это эффективно отключает защиту CORS, которая, скорее всего, подвергает ваших пользователей атаке . Если вы не знаете, что вам конкретно нужно использовать подстановочный знак, вы не должны его использовать, а вместо этого вы должны внести в белый список ваш конкретный домен:

<?php header('Access-Control-Allow-Origin: http://example.com') ?>
Мэтт Момбреа
источник
4
Я свяжусь с моим провайдером сервера. Спасибо
Рикардо
8
Есть ли какие-либо проблемы безопасности с этим? В этом ответе , например, говорится, что «JavaScript ограничен« той же политикой происхождения »по соображениям безопасности. Например, вредоносный скрипт не может связаться с удаленным сервером и отправить конфиденциальные данные с вашего сайта».
JohnK
4
Круто, я просто поместил это в файл моего сервера node.js: response.writeHead (200, {'Content-Type': contentType, 'Access-Control-Allow-Origin': '*'}); И это сработало. Спасибо!
Vbullinger
25
ДжонК, да, подстановочный знак позволит любому домену отправлять запросы на ваш хост. Я рекомендую заменить звездочку конкретным доменом, на котором вы будете запускать скрипты.
Ник
7
Интересно, что вы думаете, что подстановочный знак даже не следует предлагать @jfrej. Все зависит от вашей цели. Например, причина, по которой мы использовали подстановочный знак (и опубликовали этот ответ), заключалась в том, что мы создавали встроенный виджет для любого сайта.
Мэтт Момбреа
63

Если вы не имеете контроля над сервером, вы можете просто добавить этот аргумент для вашей пусковой установки Chrome: --disable-web-security.

Обратите внимание, что я бы не использовал это для обычного «веб-серфинга». Для справки см. Этот пост: Отключить ту же политику происхождения в Chrome .

Когда вы используете PhoneGap для фактической сборки приложения и загрузки его на устройство, это не будет проблемой.

Трэвис Уэбб
источник
Спасибо. Но мое приложение работает на мобильных устройствах, я не могу передать аргументы своей оболочке webview.
Рикардо
Разве вы сначала не тестировали свое приложение в браузере? Как вы отлаживаете?
Трэвис Уэбб
Да, я отлаживаю в браузере Chrome, но приложение не будет работать на Chrome. Это будет на веб-обозревании, которое я не могу контролировать.
Рикардо
4
Прочтите ответ: вы можете просто добавить этот аргумент в свою панель запуска Chrome . Там нет установки для этого внутри Chrome
Трэвис Уэбб
2
Конечно, это небезопасно. ФП просит обойти меры безопасности.
Трэвис Уэбб
42

Если вы используете Apache, просто добавьте:

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

в вашей конфигурации. Это приведет к тому, что все ответы с вашего веб-сервера будут доступны с любого другого сайта в Интернете. Если вы намерены разрешить использование служб на вашем хосте только определенному серверу, вы можете заменить *его URL-адресом исходного сервера:

Header set Access-Control-Allow-Origin: http://my.origin.host
Реза С
источник
3
И не забудьте загрузить модуль: a2enmod заголовки
Walery Strauch
Как загрузить модуль: a2enmod заголовки?
Айша
18

Если у вас есть приложение ASP.NET / ASP.NET MVC , вы можете включить этот заголовок через файл 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 Люди, смотрите здесь! На самом деле я собираюсь напечатать решение и указать на этот ответ в своем блоге, чтобы люди могли найти его проще. Нет ничего хуже, чем попытаться преодолеть препятствие .NET / MVC и не найти ничего, кроме решений PHP / jQuery. Спасибо @ Caio-Proiete
ottoflux
1
Почему это не работает для меня? Я использую Chrome и пытаюсь получить доступ к странице финансов Yahoo с моего локального хоста.
новичок
1
спасибо, это сработало для меня. Я добавил в проект кода на стороне сервера (web.config).
Этхемы
15

Это был первый вопрос / ответ, который возник у меня при попытке решить ту же проблему с использованием ASP.NET MVC в качестве источника моих данных. Я понимаю, что это не решает вопрос PHP , но это достаточно связано, чтобы быть ценным.

Я использую ASP.NET MVC. Сообщение в блоге от Грега Бранта работало на меня. В конечном итоге вы создаете атрибут, [HttpHeaderAttribute("Access-Control-Allow-Origin", "*")]который вы можете добавить к действиям контроллера.

Например:

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

И затем использовать его с:

[HttpHeaderAttribute("Access-Control-Allow-Origin", "*")]
public ActionResult MyVeryAvailableAction(string id)
{
    return Json( "Some public result" );
}
badMonkey
источник
1
В WebApi 2 это встроено. asp.net/web-api/overview/security/…
Мэтт Фрир
10

Так как Мэтт Момбреа подходит для серверной части, вы можете столкнуться с другой проблемой - отказом из белого списка.

Вы должны настроить свой phonegap.plist. (Я использую старую версию телефонного зазора)

Для кордовы могут быть некоторые изменения в именовании и каталоге. Но шаги должны быть в основном одинаковыми.

Сначала выберите Вспомогательные файлы> PhoneGap.plist

введите описание изображения здесь

затем в разделе "Внешние хосты"

Добавьте запись со значением, возможно, " http://nqatalog.negroesquisso.pt ", которое я использую * только для целей отладки.

введите описание изображения здесь

steve0hh
источник
8

Это может быть удобно для тех, кому нужно исключение для версий реферера как с www, так и без www:

 $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');
 }
lewsid
источник
Я указал верное направление в устранении ошибки ACAO лазурью. Пока я добавил разрешенное имя хоста googledrive. Используемый URL должен быть googledrive, а не googledrive
Kildareflare
7

Я дам вам простое решение для этого. В моем случае у меня нет доступа к серверу. В этом случае вы можете изменить политику безопасности в браузере Google Chrome, чтобы разрешить Access-Control-Allow-Origin. Это очень просто:

  1. Создать ярлык браузера Chrome
  2. Щелкните правой кнопкой мыши значок ярлыка -> Свойства -> Ярлык -> Цель

Простая вставка "C:\Program Files\Google\Chrome\Application\chrome.exe" --allow-file-access-from-files --disable-web-security.

Расположение может отличаться. Теперь откройте Chrome, нажав на этот ярлык.

Dibish
источник
7

Я сталкивался с этим несколько раз при работе с различными API. Часто для быстрого исправления добавьте "& callback =?" до конца строки. Иногда амперсанд должен быть символьным кодом, а иногда "?": "? Callback =?" (см. Использование API Forecast.io с jQuery )

Фрэнсис Батист
источник
6

Если вы пишете расширение Chrome и получить эту ошибку, то убедитесь , что вы добавили базовый URL в API, чтобы ваш manifest.json«s разрешения блока , например:

"permissions": [
    "https://itunes.apple.com/"
]
itzg
источник
6

Это из -за политики того же происхождения . Смотрите больше в Mozilla Developer Network или Википедии .

По сути, в вашем примере вам нужно загружать http://nqatalog.negroesquisso.pt/login.phpстраницу только из nqatalog.negroesquisso.pt, а не из localhost.

antyrat
источник
1
Но мне нужно загрузить веб-сервис с мобильного устройства, я бы обойти это?
Рикардо
Ну, вам нужно внести некоторые изменения на стороне сервера или использовать JSONP en.wikipedia.org/wiki/JSONP
antyrat
6

если вы находитесь в Apache, просто добавьте файл .htaccess в ваш каталог со следующим содержимым:

Header set Access-Control-Allow-Origin: *

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

Header set Access-Control-Allow-Methods: *
Vero O
источник
5

В Ruby on Rails вы можете сделать в контроллере:

headers['Access-Control-Allow-Origin'] = '*'
fuzzyalej
источник
в каком контроллере вы это поместите, если это AJAX-вызов? Могу ли я увидеть больше кода?
Rigdonmr
5

Вы можете заставить его работать без модификации сервера, добавив заголовок Access-Control-Allow-Origin: *в ответы HTTP OPTIONS.

В Chrome используйте это расширение . Если вы находитесь на Mozilla, проверьте этот ответ .

forzagreen
источник
5

Если вы получите это в Angular.js, то убедитесь, что вы экранировали свой номер порта следующим образом:

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

Смотрите здесь для получения дополнительной информации об этом.

Marius
источник
4

У нас также есть такая же проблема с приложением phonegap, протестированным в Chrome. Одна машина Windows, которую мы используем ниже пакетного файла каждый день перед открытием Chrome. Помните, что перед запуском вам нужно очистить весь экземпляр Chrome из диспетчера задач, или вы можете выбрать Chrome, чтобы не запускать его в фоновом режиме.

BATCH: (используйте cmd)

cd D:\Program Files (x86)\Google\Chrome\Application\chrome.exe --disable-web-security
abksharma
источник
1

В Руби Синатре

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

для всех или

response['Access-Control-Allow-Origin'] = 'http://yourdomain.name' 
Михаил Чупринский
источник
0

Когда вы получите запрос, вы можете

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

чем когда вы должны ответить, пойти с чем-то вроде этого:

res.writeHead(
    206,
    {
        'Access-Control-Allow-Credentials': true,
        'Access-Control-Allow-Origin': origin,
    }
);
Алессандро Аннини
источник