WedX - журнал о программировании и компьютерных науках

Настройка Access-Control-Allow-Origin в ASP.Net MVC - самый простой из возможных способов

У меня есть простой метод действия, который возвращает некоторый json. Он работает на ajax.example.com. Мне нужно получить к нему доступ с другого сайта someothersite.com.

Если я попытаюсь вызвать это, я получу ожидаемый ...:

Origin https://someothersite.com is not allowed by Access-Control-Allow-Origin.

Я знаю два способа обойти это: JSONP и создание настраиваемого HttpHandler для установить заголовок.

Нет более простого способа?

Разве невозможно простым действием определить список разрешенных источников происхождения или просто разрешить всем? Может быть, фильтр действий?

Оптимальным было бы ...:

return json(mydata, JsonBehaviour.IDontCareWhoAccessesMe);

Ответы:


1

Для простых контроллеров ASP.NET MVC

Создать новый атрибут

public class AllowCrossSiteJsonAttribute : ActionFilterAttribute
{
    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        filterContext.RequestContext.HttpContext.Response.AddHeader("Access-Control-Allow-Origin", "*");
        base.OnActionExecuting(filterContext);
    }
}

Отметьте свое действие:

[AllowCrossSiteJson]
public ActionResult YourMethod()
{
    return Json("Works better?");
}

Для веб-API ASP.NET

using System;
using System.Web.Http.Filters;

public class AllowCrossSiteJsonAttribute : ActionFilterAttribute
{
    public override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext)
    {
        if (actionExecutedContext.Response != null)
            actionExecutedContext.Response.Headers.Add("Access-Control-Allow-Origin", "*");

        base.OnActionExecuted(actionExecutedContext);
    }
}

Отметьте весь контроллер API:

[AllowCrossSiteJson]
public class ValuesController : ApiController
{

Или отдельные вызовы API:

[AllowCrossSiteJson]
public IEnumerable<PartViewModel> Get()
{
    ...
}

Для Internet Explorer ‹= v9

IE ‹= 9 не поддерживает CORS. Я написал javascript, который автоматически маршрутизирует эти запросы через прокси. Все это на 100% прозрачно (вам просто нужно включить мой прокси и скрипт).

Загрузите его с помощью nuget corsproxy и следуйте прилагаемым инструкциям.

Запись в блоге | Исходный код

09.06.2011
  • в восторге от элегантности этого решения 14.12.2012
  • Вы можете легко расширить атрибут, чтобы принять конкретное происхождение, если хотите ограничить CORS своими собственными доменами. 22.02.2013
  • Вы должны иметь возможность добавить это в RegisterHttpFilters в вашем App_Start \ FilterConfig, правильно? Это применит его ко всем контроллерам Api в вашем проекте. Соединяя это с комментарием Pate выше, вы можете ограничить CORS своим доменом (ами) для всех контроллеров. 12.03.2013
  • Это также работает, если у вас есть базовый класс контроллера и вы делаете это в методе OnActionExecuting. 29.05.2013
  • Я обнаружил, что этот метод не работает с командой PUT http. Вместо этого я использовал: brockallen.com/2012/06/28/ 03.09.2013
  • Теперь у Microsoft есть пакет NuGet, который делает это (и многое другое). nuget.org/packages /Microsoft.AspNet.WebApi.Cors 29.05.2015
  • Недавно я обновил наш проект до MVC 5 и попытался это сделать. Кажется, даже добавление заголовка в фильтр не работает. Когда я просматриваю запрос в сети, в ответе нет заголовка. Что еще нужно сделать, чтобы это заработало? 02.03.2016
  • Я хочу добавить настраиваемый заголовок во время выполнения, как передать массив белого списка URL-адресов, который может получить доступ к API? 30.03.2017
  • Если я чего-то не упустил, этот атрибут не является эксклюзивным для JSON. 13.04.2020

  • 2

    Если вы используете IIS 7+, вы можете поместить файл web.config в корень папки, указав его в разделе system.webServer:

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

    См .: https://msdn.microsoft.com/en-us/library/ms178685.aspx И: https://enable-cors.org/#how-iis7

    15.07.2012
  • Уже не могу вспомнить почему, но этот метод не всегда работает в IIS 7+ 09.01.2013
  • Хм. Единственная причина, по которой я могу думать, что это не сработает, - это если запрос исходит из браузера, отличного от CORS. Но я продолжу расследование. 09.01.2013
  • Кроме того, это сделает весь веб-сайт CORS-дружественным. Если кто-то хочет пометить только одно действие или контроллер как дружественный к CORS, то принятый ответ будет намного лучше. 08.02.2013
  • Если вы видите раздел ASP.Net, в нем есть подсказка : Примечание: этот подход совместим с IIS6, классическим режимом IIS7 и интегрированным режимом IIS7. 14.12.2013
  • Я думаю, что единственный недостаток этого метода в том, что он требует дополнительного шага при развертывании. 02.02.2014
  • @LaundroMatt Я не понимаю <clear /> в этом примере. это требуется по какой-то причине? 15.04.2014
  • Когда я публикую свое приложение в среде SharePoint, я сталкиваюсь с проблемой междоменного доступа. Когда я запускаю свое приложение в локальной среде, мое приложение работает нормально, но когда я публикую его на лазурном сервере на моем сайте sharepoint, оно перенаправляется на страницу ошибки при вызове формы Ajax.Begin. Я пробовал это решение, но оно у меня не работает. Есть ли ему другая альтернатива? 04.09.2017

  • 3

    Я столкнулся с проблемой, когда браузер отказывался обслуживать контент, который он получил, когда запрос был передан в куки (например, xhr имел свое withCredentials=true), а для сайта Access-Control-Allow-Origin было установлено значение *. (Ошибка в Chrome была: «Невозможно использовать подстановочный знак в Access-Control-Allow-Origin, когда флаг учетных данных истинен».)

    Основываясь на ответе @jgauffin, я создал это, что в основном является способом обхода этой конкретной проверки безопасности браузера, поэтому будьте осторожны.

    public class AllowCrossSiteJsonAttribute : ActionFilterAttribute
    {
        public override void OnActionExecuting(ActionExecutingContext filterContext)
        {
            // We'd normally just use "*" for the allow-origin header, 
            // but Chrome (and perhaps others) won't allow you to use authentication if
            // the header is set to "*".
            // TODO: Check elsewhere to see if the origin is actually on the list of trusted domains.
            var ctx = filterContext.RequestContext.HttpContext;
            var origin = ctx.Request.Headers["Origin"];
            var allowOrigin = !string.IsNullOrWhiteSpace(origin) ? origin : "*";
            ctx.Response.AddHeader("Access-Control-Allow-Origin", allowOrigin);
            ctx.Response.AddHeader("Access-Control-Allow-Headers", "*");
            ctx.Response.AddHeader("Access-Control-Allow-Credentials", "true");
            base.OnActionExecuting(filterContext);
        }
    }
    
    07.09.2013

    4

    Это действительно просто, просто добавьте это в web.config

    <system.webServer>
      <httpProtocol>
        <customHeaders>
          <add name="Access-Control-Allow-Origin" value="https://localhost" />
          <add name="Access-Control-Allow-Headers" value="X-AspNet-Version,X-Powered-By,Date,Server,Accept,Accept-Encoding,Accept-Language,Cache-Control,Connection,Content-Length,Content-Type,Host,Origin,Pragma,Referer,User-Agent" />
          <add name="Access-Control-Allow-Methods" value="GET, PUT, POST, DELETE, OPTIONS" />
          <add name="Access-Control-Max-Age" value="1000" />
        </customHeaders>
      </httpProtocol>
    </system.webServer>
    

    В Origin поместите все домены, которые имеют доступ к вашему веб-серверу, в заголовки поместите все возможные заголовки, которые может использовать любой HTTP-запрос ajax, в методах поместите все методы, которые вы разрешаете на своем сервере

    С уважением :)

    11.12.2015
  • Добавление авторизации в Access-Control-Allow-Headers также может быть полезно, если вы собираетесь использовать авторизованные запросы. 18.01.2017

  • 5

    Иногда глагол OPTIONS также вызывает проблемы

    Просто: обновите свой web.config следующим образом

    <system.webServer>
        <httpProtocol>
            <customHeaders>
              <add name="Access-Control-Allow-Origin" value="*" />
              <add name="Access-Control-Allow-Headers" value="Origin, X-Requested-With, Content-Type, Accept" />
            </customHeaders>
        </httpProtocol>
    </system.webServer>
    

    И обновите заголовки веб-службы / контроллера с помощью httpGet и httpOptions

    // GET api/Master/Sync/?version=12121
            [HttpGet][HttpOptions]
            public dynamic Sync(string version) 
            {
    
    11.09.2013
  • Кстати, в sitefinity вам нужно добавить * в расширенные настройки системы в разделе безопасности 03.09.2014
  • в каких файлах мне нужно обновить заголовки контроллера? 19.10.2014

  • 6

    В WebAPI 2 теперь есть пакет для CORS, который можно установить с помощью: Install-Package Microsoft.AspNet.WebApi.Cors -pre -project WebServic

    После его установки введите код: https://www.asp.net/web-api/overview/security/enpting-cross-origin-requests-in-web-api

    12.04.2014

    7

    Добавьте эту строку в свой метод, если вы используете API.

    HttpContext.Current.Response.AddHeader("Access-Control-Allow-Origin", "*"); 
    
    14.03.2014

    8

    Это руководство является очень полезный. Вкратце:

    1. Используйте пакет CORS, доступный на Nuget: Install-Package Microsoft.AspNet.WebApi.Cors

    2. В вашем WebApiConfig.cs файле добавьте config.EnableCors() к Register() методу.

    3. Добавьте атрибут к контроллерам, которые вам нужны для обработки cors:

    [EnableCors(origins: "<origin address in here>", headers: "*", methods: "*")]

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

  • 9

    Есть разные способы передачи заголовков Access-Control-Expose-Headers.

    • Как объяснил jgauffin, мы можем создать новый атрибут.
    • Как объяснил LaundroMatt, мы можем добавить в файл web.config.
    • Другой способ - добавить код, как показано ниже, в файл webApiconfig.cs.

      config.EnableCors (новый EnableCorsAttribute ("", заголовки: "", методы: "*", visibleHeaders: "TestHeaderToExpose") {SupportsCredentials = true});

    Или мы можем добавить код ниже в файл Global.Asax.

    protected void Application_BeginRequest()
            {
                if (HttpContext.Current.Request.HttpMethod == "OPTIONS")
                {
                    //These headers are handling the "pre-flight" OPTIONS call sent by the browser
                    HttpContext.Current.Response.AddHeader("Access-Control-Allow-Methods", "GET, POST, OPTIONS");
                    HttpContext.Current.Response.AddHeader("Access-Control-Allow-Headers", "*");
                    HttpContext.Current.Response.AddHeader("Access-Control-Allow-Credentials", "true");
                    HttpContext.Current.Response.AddHeader("Access-Control-Allow-Origin", "https://localhost:4200");
                    HttpContext.Current.Response.AddHeader("Access-Control-Expose-Headers", "TestHeaderToExpose");
                    HttpContext.Current.Response.End();
                }
            }
    

    Я написал это для вариантов. Пожалуйста, измените то же самое в соответствии с вашими потребностями.

    Удачного кодирования !!

    11.10.2018

    10

    После целого вечера борьбы я наконец заставил это работать. После некоторой отладки я обнаружил, что проблема, с которой я столкнулся, заключалась в том, что мой клиент отправлял так называемый запрос параметров предварительной проверки, чтобы проверить, разрешено ли приложению отправлять почтовый запрос с предоставленным источником, методами и заголовками. Я не хотел использовать Owin или APIController, поэтому я начал копать и придумал следующее решение с использованием только ActionFilterAttribute. Особенно важна часть «Access-Control-Allow-Headers», поскольку упомянутые там заголовки должны совпадать с заголовками, которые отправляет ваш запрос.

    using System.Linq;
    using System.Web;
    using System.Web.Mvc;
    
    namespace MyNamespace
    {
        public class AllowCrossSiteJsonAttribute : ActionFilterAttribute
        {
            public override void OnActionExecuting(ActionExecutingContext filterContext)
            {
                HttpRequest request = HttpContext.Current.Request;
                HttpResponse response = HttpContext.Current.Response;
    
                // check for preflight request
                if (request.Headers.AllKeys.Contains("Origin") && request.HttpMethod == "OPTIONS")
                {
                    response.AppendHeader("Access-Control-Allow-Origin", "*");
                    response.AppendHeader("Access-Control-Allow-Credentials", "true");
                    response.AppendHeader("Access-Control-Allow-Methods", "GET, PUT, POST, DELETE");
                    response.AppendHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, X-RequestDigest, Cache-Control, Content-Type, Accept, Access-Control-Allow-Origin, Session, odata-version");
                    response.End();
                }
                else
                {
                    HttpContext.Current.Response.Cache.SetCacheability(HttpCacheability.NoCache);
                    HttpContext.Current.Response.Cache.SetNoStore();
    
                    response.AppendHeader("Access-Control-Allow-Origin", "*");
                    response.AppendHeader("Access-Control-Allow-Credentials", "true");
                    if (request.HttpMethod == "POST")
                    {
                        response.AppendHeader("Access-Control-Allow-Methods", "GET, PUT, POST, DELETE");
                        response.AppendHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, X-RequestDigest, Cache-Control, Content-Type, Accept, Access-Control-Allow-Origin, Session, odata-version");
                    }
    
                    base.OnActionExecuting(filterContext);
                }
            }
        }
    }
    

    Наконец, мой метод действия MVC выглядит так. Здесь важно также упомянуть параметры HttpVerbs, потому что в противном случае предварительный запрос не будет выполнен.

    [AcceptVerbs(HttpVerbs.Post | HttpVerbs.Options)]
    [AllowCrossSiteJson]
    public async Task<ActionResult> Create(MyModel model)
    {
        return Json(await DoSomething(model));
    }
    
    09.10.2019

    11

    В Web.config введите следующее

    <system.webServer>
    <httpProtocol>
      <customHeaders>
        <clear />     
        <add name="Access-Control-Allow-Credentials" value="true" />
        <add name="Access-Control-Allow-Origin" value="https://localhost:123456(etc)" />
      </customHeaders>
    </httpProtocol>
    
    27.03.2018

    12

    Если вы используете IIS, я бы посоветовал попробовать Модуль IIS CORS.
    Он прост в настройке и работает со всеми типами контроллеров.

    Вот пример конфигурации:

        <system.webServer>
            <cors enabled="true" failUnlistedOrigins="true">
                <add origin="*" />
                <add origin="https://*.microsoft.com"
                     allowCredentials="true"
                     maxAge="120"> 
                    <allowHeaders allowAllRequestedHeaders="true">
                        <add header="header1" />
                        <add header="header2" />
                    </allowHeaders>
                    <allowMethods>
                         <add method="DELETE" />
                    </allowMethods>
                    <exposeHeaders>
                        <add header="header1" />
                        <add header="header2" />
                    </exposeHeaders>
                </add>
                <add origin="https://*" allowed="false" />
            </cors>
        </system.webServer>
    
    29.01.2019

    13

    Я использую DotNet Core MVC, и после нескольких часов борьбы с пакетами nuget, Startup.cs, атрибутами и этим местом я просто добавил это в действие MVC:

    Response.Headers.Add("Access-Control-Allow-Origin", "*");
    

    Я понимаю, что это довольно неуклюже, но это все, что мне нужно, и больше никто не хотел добавлять эти заголовки. Надеюсь, это поможет кому-то другому!

    24.06.2020

    14

    Чтобы основной ответ работал в MVC 5.

    Используйте System.Web.Mvc вместо System.Web.Http.Filters.

    using System;
    using System.Web.Mvc;
    // using System.Web.Http.Filters;
    
    public class AllowCrossSiteJsonAttribute : ActionFilterAttribute
    {
       ...
    }
    
    05.03.2021
    Новые материалы

    Как проанализировать работу вашего классификатора?
    Не всегда просто знать, какие показатели использовать С развитием глубокого обучения все больше и больше людей учатся обучать свой первый классификатор. Но как только вы закончите..

    Работа с цепями Маркова, часть 4 (Машинное обучение)
    Нелинейные цепи Маркова с агрегатором и их приложения (arXiv) Автор : Бар Лайт Аннотация: Изучаются свойства подкласса случайных процессов, называемых дискретными нелинейными цепями Маркова..

    Crazy Laravel Livewire упростил мне создание электронной коммерции (панель администратора и API) [Часть 3]
    Как вы сегодня, ребята? В этой части мы создадим CRUD для данных о продукте. Думаю, в этой части я не буду слишком много делиться теорией, но чаще буду делиться своим кодом. Потому что..

    Использование машинного обучения и Python для классификации 1000 сезонов новичков MLB Hitter
    Чему может научиться машина, глядя на сезоны новичков 1000 игроков MLB? Это то, что исследует это приложение. В этом процессе мы будем использовать неконтролируемое обучение, чтобы..

    Учебные заметки: создание моего первого пакета Node.js
    Это мои обучающие заметки, когда я научился создавать свой самый первый пакет Node.js, распространяемый через npm. Оглавление Глоссарий I. Новый пакет 1.1 советы по инициализации..

    Забудьте о Matplotlib: улучшите визуализацию данных с помощью умопомрачительных функций Seaborn!
    Примечание. Эта запись в блоге предполагает базовое знакомство с Python и концепциями анализа данных. Привет, энтузиасты данных! Добро пожаловать в мой блог, где я расскажу о невероятных..

    ИИ в аэрокосмической отрасли
    Каждый полет – это шаг вперед к великой мечте. Чтобы это происходило в их собственном темпе, необходима команда астронавтов для погони за космосом и команда технического обслуживания..


    Для любых предложений по сайту: [email protected]