Подтвердить что ты не робот

Asp.Net WebApi2 Включите CORS, не работая с AspNet.WebApi.Cors 5.2.3

Я попытался выполнить шаги в http://enable-cors.org/server_aspnet.html чтобы мой RESTful API (реализованный с ASP.NET WebAPI2) работал с запросами на кросс-начало (CORS Enabled). Он не работает, если я не изменяю web.config.

Я установил зависимость WebApi Cors:

install-package Microsoft.AspNet.WebApi.Cors -ProjectName MyProject.Web.Api

Тогда в моем App_Start у меня есть класс WebApiConfig следующим образом:

public static class WebApiConfig
{
    public static void Register(HttpConfiguration config)
    {
        var corsAttr = new EnableCorsAttribute("*", "*", "*");
        config.EnableCors(corsAttr);

        var constraintsResolver = new DefaultInlineConstraintResolver();

        constraintsResolver.ConstraintMap.Add("apiVersionConstraint", typeof(ApiVersionConstraint));
        config.MapHttpAttributeRoutes(constraintsResolver); 
        config.Services.Replace(typeof(IHttpControllerSelector), new NamespaceHttpControllerSelector(config));
        //config.EnableSystemDiagnosticsTracing(); 
        config.Services.Replace(typeof(ITraceWriter), new SimpleTraceWriter(WebContainerManager.Get<ILogManager>())); 
        config.Services.Add(typeof(IExceptionLogger), new SimpleExceptionLogger(WebContainerManager.Get<ILogManager>()));
        config.Services.Replace(typeof(IExceptionHandler), new GlobalExceptionHandler()); 
    }
}

но после этого я запускаю приложение, я запрашиваю ресурс с помощью Fiddler: http://localhost:51589/api/v1/persons и в ответе я не вижу заголовков HTTP, которые я должен видеть, например:

  • Access-Control-Allow-Methods: POST, PUT, DELETE, GET, OPTIONS
  • Access-Control-Allow-Origin: *

Я пропустил какой-то шаг? Я пробовал со следующей аннотацией на контроллере:

[EnableCors(origins: "http://example.com", headers: "*", methods: "*")]

Тот же результат, CORS не включен.

Однако, если я добавлю следующее в свой web.config(даже не устанавливая зависимость AspNet.WebApi.Cors), он работает:

<system.webServer>

<httpProtocol>
  <!-- THESE HEADERS ARE IMPORTANT TO WORK WITH CORS -->
  <!--
  <customHeaders>
    <add name="Access-Control-Allow-Origin" value="*" />
    <add name="Access-Control-Allow-Methods" value="POST, PUT, DELETE, GET, OPTIONS" />
    <add name="Access-Control-Allow-Headers" value="content-Type, accept, origin, X-Requested-With, Authorization, name" />
    <add name="Access-Control-Allow-Credentials" value="true" />
  </customHeaders>
  -->
</httpProtocol>
<handlers>
  <!-- THESE HANDLERS ARE IMPORTANT FOR WEB API TO WORK WITH  GET,HEAD,POST,PUT,DELETE and CORS-->
  <!--

  <remove name="WebDAV" />
  <add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="GET,HEAD,POST,PUT,DELETE" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
  <remove name="ExtensionlessUrlHandler-Integrated-4.0" />
  <remove name="OPTIONSVerbHandler" />
  <remove name="TRACEVerbHandler" />
  <add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="*" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
-->
</handlers>

Любая помощь будет очень признательна!

Спасибо.

4b9b3361

Ответ 1

Я создал для вас демонстрационный проект по сокращению.

Вы можете попробовать вышеупомянутую ссылку API из локального Fiddler, чтобы просмотреть заголовки. Вот объяснение.

Global.ascx

Все это вызывает вызов WebApiConfig. Это ничего, кроме организации кода.

public class WebApiApplication : System.Web.HttpApplication
{
    protected void Application_Start()
    {
        WebApiConfig.Register(GlobalConfiguration.Configuration);
    }
}

WebApiConfig.cs

Ключевым методом для вас является метод EnableCrossSiteRequests. Это все, что вам нужно сделать. EnableCorsAttribute - это атрибут CORS, скорректированный на глобальном уровне.

public static class WebApiConfig
{
    public static void Register(HttpConfiguration config)
    {
        EnableCrossSiteRequests(config);
        AddRoutes(config);
    }

    private static void AddRoutes(HttpConfiguration config)
    {
        config.Routes.MapHttpRoute(
            name: "Default",
            routeTemplate: "api/{controller}/"
        );
    }

    private static void EnableCrossSiteRequests(HttpConfiguration config)
    {
        var cors = new EnableCorsAttribute(
            origins: "*", 
            headers: "*", 
            methods: "*");
        config.EnableCors(cors);
    }
}

Контроллер значений

Метод Get получает атрибут EnableCors, который мы применили глобально. Метод Another переопределяет глобальный EnableCors.

public class ValuesController : ApiController
{
    // GET api/values
    public IEnumerable<string> Get()
    {
        return new string[] { 
            "This is a CORS response.", 
            "It works from any origin." 
        };
    }

    // GET api/values/another
    [HttpGet]
    [EnableCors(origins:"http://www.bigfont.ca", headers:"*", methods: "*")]
    public IEnumerable<string> Another()
    {
        return new string[] { 
            "This is a CORS response. ", 
            "It works only from two origins: ",
            "1. www.bigfont.ca ",
            "2. the same origin." 
        };
    }
}

Web.config

Вам не нужно добавлять что-либо особенное в web.config. На самом деле это то, что выглядит demo web.config - он пуст.

<?xml version="1.0" encoding="utf-8"?>
<configuration>
</configuration>

Demo

var url = "https://cors-webapi.azurewebsites.net/api/values"

$.get(url, function(data) {
  console.log("We expect this to succeed.");
  console.log(data);
});

var url = "https://cors-webapi.azurewebsites.net/api/values/another"

$.get(url, function(data) {
  console.log(data);
}).fail(function(xhr, status, text) {
  console.log("We expect this to fail.");
  console.log(status);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

Ответ 2

Вам просто нужно изменить некоторые файлы. Это работает для меня.

Global.ascx

public class WebApiApplication : System.Web.HttpApplication {
    protected void Application_Start()
    {
        WebApiConfig.Register(GlobalConfiguration.Configuration);
    } }

WebApiConfig.cs

Все запросы должны вызывать этот код.

public static class WebApiConfig {
    public static void Register(HttpConfiguration config)
    {
        EnableCrossSiteRequests(config);
        AddRoutes(config);
    }

    private static void AddRoutes(HttpConfiguration config)
    {
        config.Routes.MapHttpRoute(
            name: "Default",
            routeTemplate: "api/{controller}/"
        );
    }

    private static void EnableCrossSiteRequests(HttpConfiguration config)
    {
        var cors = new EnableCorsAttribute(
            origins: "*", 
            headers: "*", 
            methods: "*");
        config.EnableCors(cors);
    } }

Некоторые контроллеры

Ничего не изменится.

Web.config

Вам нужно добавить обработчики в ваш web.config

<configuration> 
  <system.webServer>
    <handlers>
      <remove name="ExtensionlessUrlHandler-Integrated-4.0" />
      <remove name="OPTIONSVerbHandler" />
      <remove name="TRACEVerbHandler" />
      <add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="*" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
    </handlers>   
  </system.webServer> 
</configuration>

Ответ 3

В случае запроса CORS все современные браузеры отвечают глаголом OPTION, а затем выполняется фактический запрос. Предполагается, что это будет использоваться для запроса пользователю подтверждения в случае запроса CORS. Но в случае API, если вы хотите пропустить этот процесс проверки, добавьте следующий фрагмент в Global.asax

        protected void Application_BeginRequest(object sender, EventArgs e)
        {
            HttpContext.Current.Response.AddHeader("Access-Control-Allow-Origin", "*");
            if (HttpContext.Current.Request.HttpMethod == "OPTIONS")
            {
                HttpContext.Current.Response.AddHeader("Access-Control-Allow-Methods", "POST, PUT, DELETE");

                HttpContext.Current.Response.AddHeader("Access-Control-Allow-Headers", "Content-Type, Accept");
                HttpContext.Current.Response.AddHeader("Access-Control-Max-Age", "1728000");
                HttpContext.Current.Response.End();
            }
        }

Здесь мы просто передаем проверку, проверяя глагол OPTIONS.

Ответ 4

Я только добавил пользовательские заголовки в Web.config, и это сработало как шарм.

В конфигурации - system.webServer:

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

У меня есть приложение для внешнего интерфейса и бэкэнд на том же самом решении. Для этого мне нужно настроить проект веб-сервисов (Backend) как по умолчанию для этого.

Я использовал ReST, не пробовал ни с чем другим.

Ответ 5

После некоторых изменений в моем Web.config CORS неожиданно перестала работать в моем проекте Web API 2 (по крайней мере, для запроса OPTIONS во время предполета). Кажется, что вам нужно иметь упомянутый ниже раздел в вашем Web.config или иначе (глобальный) EnableCorsAttribute не будет работать с запросами OPTIONS. Обратите внимание, что это тот же самый раздел. Visual Studio добавит новый проект Web API 2.

<system.webServer>
  <handlers>
    <remove name="ExtensionlessUrlHandler-Integrated-4.0"/>
    <remove name="OPTIONSVerbHandler"/>
    <remove name="TRACEVerbHandler"/>
    <add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="*" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0"/>
  </handlers>
</system.webServer>

Ответ 6

Ни один из этих ответов не работает. Как отмечали другие, пакет Cors будет использовать заголовок Access-Control-Allow-Origin, если у запроса был заголовок Origin. Но вы не можете просто добавить заголовок Origin в запрос, так как браузеры также могут его регулировать.

Если вам нужен быстрый и грязный способ разрешить запросы на межсайтовый сайт для веб-api, гораздо проще просто написать собственный атрибут фильтра:

public class AllowCors : ActionFilterAttribute
{
    public override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext)
    {
        if (actionExecutedContext == null)
        {
            throw new ArgumentNullException("actionExecutedContext");
        }
        else
        {
            actionExecutedContext.Response.Headers.Remove("Access-Control-Allow-Origin");
            actionExecutedContext.Response.Headers.Add("Access-Control-Allow-Origin", "*");
        }
        base.OnActionExecuted(actionExecutedContext);
    }
}

Затем просто используйте его в своем действии Controller:

[AllowCors]
public IHttpActionResult Get()
{
    return Ok("value");
}

Я не буду ручаться за безопасность этого вообще, но он, вероятно, намного безопаснее, чем установка заголовков в web.config, так как вы можете применять их только так, как вам нужно.

И, конечно, просто изменить приведенное выше, чтобы разрешить только определенные источники, методы и т.д.

Ответ 7

Я только что испытал эту же проблему, пытаясь включить CORS во всем мире. Однако я обнаружил, что это работает, однако только тогда, когда запрос содержит значение заголовка Origin. Если вы опустите значение заголовка Origin, ответ не будет содержать Access-Control-Allow-Origin.

Я использовал хром-плагин под названием DHC для проверки моего запроса GET. Это позволило мне легко добавить заголовок Origin.

Ответ 8

WEBAPI2: РЕШЕНИЕ. Global.asax.cs:

var cors = new EnableCorsAttribute("*", "*", "*");
config.EnableCors(cors);

В проводнике решений, щелкните правой кнопкой мыши api-project. В свойств окна "Анонимная аутентификация" до Включено!!!

Надеюсь, это поможет кому-то в будущем.

Ответ 9

Я нашел этот вопрос, потому что у меня возникли проблемы с запросом OPTIONS, отправляемым большинством браузеров. Мое приложение маршрутизировало запросы OPTIONS и использовало мой IoC для создания большого количества объектов, а некоторые из них исключали исключения из этого нечетного типа запроса по разным причинам.

По существу, в маршрут игнорирования для всех запросов OPTIONS, если они вызывают проблемы:

var constraints = new { httpMethod = new HttpMethodConstraint(HttpMethod.Options) };
config.Routes.IgnoreRoute("OPTIONS", "{*pathInfo}", constraints);

Дополнительная информация: Обработка запросов веб-API от OPTIONS

Ответ 10

Надеюсь, это поможет кому-то в будущем. Моя проблема заключалась в том, что я следовал тому же учебнику, что и OP, чтобы включить глобальный CORS. Однако в моем файле AccountController.cs я также установил правило CORS для конкретных действий:

[EnableCors(origins: "", headers: "*", methods: "*")]

и возникла ошибка о происхождении не может быть пустой или пустой строкой. НО ошибка происходила в файле Global.asax.cs всех мест. Решение состоит в том, чтобы изменить его на:

[EnableCors(origins: "*", headers: "*", methods: "*")]

обратите внимание * на происхождение? Отсутствие этого было причиной ошибки в файле Global.asax.cs.

Надеюсь, это поможет кому-то.

Ответ 11

Ни одно безопасное решение для меня не сработало, поэтому быть безопаснее, чем Neeraj, и проще, чем Мэтью, просто добавьте: System.Web.HttpContext.Current.Response.AddHeader("Access-Control-Allow-Origin", "*");

В вашем методе контроллера. Это работа для меня.

public IHttpActionResult Get()
{
    System.Web.HttpContext.Current.Response.AddHeader("Access-Control-Allow-Origin", "*");
    return Ok("value");
}