Проблемы CORS в WebAPI, размещенном в IIS

Я пытаюсь реализовать приложение, использующее тот же механизм аутентификации на основе токенов, который показан в этом отличный пример от Taiseer Joudeh.

В моем приложении я продолжал сталкиваться с проблемами Cors. В некоторых конфигурациях я получаю ошибку 500 в предварительном запросе (OPTIONS) для POST, чтобы получить токен, или я могу получить токен, но затем получаю ошибку 404 в предварительном запросе для запроса GET к фактическому вызову API с помощью Жетон предъявителя.

Одно из отличий заключалось в том, что код Taiseer был настроен для размещения в IISExpress (или Azure), а мой — в Local IIS (на данный момент работает в Windows 7).

По наитию я попытался разместить его API под локальным IIS и обнаружил ту же проблему. (Ошибка 500 при предварительном запросе токена, и похоже, что фактический API будет работать правильно)

Из того, что я читал, кажется, что это может быть некоторый конфликт между модулями и обработчиками в IIS и реализацией Cors в WebApi, но реализация Taiseer работает при размещении в Azure, поэтому, возможно, это разница в версии IIS (я m в настоящее время работает под управлением Windows 7).

Как я могу разобраться, что вызывает проблему?


person RonnBlack    schedule 20.04.2016    source источник
comment
Вы должны быть более конкретными в отношении ошибки, которую вы получаете. Выясните, какое исключение вызывает ошибку сервера 500 (при необходимости попробуйте выполнить удаленную отладку), или если никто не найдет внутреннюю ошибку IIS в журналах. У нас недостаточно информации, чтобы помочь вам в данный момент.   -  person Federico Dipuma    schedule 20.04.2016


Ответы (3)


Корень проблемы

Действие Token не размещается в контроллере, а вместо этого встроено где-то в сантехнику нижнего уровня. Доступ к механизму возможен только через метод переопределения GrantResourceOwnerCredentials() в классе, расширяющем OAuthAuthorizationServerProvider. (В нашем случае это ApplicationOAuthProvider.cs).

GrantResourceOwnerCredentials() имеет доступный контекст, но он не вызывается как часть запроса PreFlight, поэтому у вас нет возможности вставить соответствующие заголовки ответов PreFlight для CORS.

Решение

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

Решение состояло в том, чтобы переопределить метод Application_PreSendRequestHeaders() в Global.asax, чтобы вставить соответствующие заголовки.

Global.asax.cs

    void Application_PreSendRequestHeaders(Object sender, EventArgs e)
    {
        var origin = Request.Headers.Get("Origin");
        var validOrigins = ConfigurationManager.AppSettings["allowedCorsOrigins"].Split(',');
        if(validOrigins.Any(o => o == origin))
        {
            Response.Headers.Set("Access-Control-Allow-Origin", origin);
            Response.Headers.Set("Access-Control-Allow-Credentials", "true");
            Response.Headers.Set("Access-Control-Allow-Headers", "Content-Type, Accept, Authorization, withcredentials, Prefer");
            Response.Headers.Set("Access-Control-Expose-Headers", "Claims, *");
            Response.Headers.Set("Access-Control-Max-Age", "600");
            Response.Headers.Set("Access-Control-Allow-Methods", "GET,PUT,POST,DELETE,OPTIONS");
        }
    }

Для этого требуются следующие записи web.config:

web.config

<configuration>
  <appSettings>
    <add key="allowedCorsOrigins" value="http://www.allowedsite1.net,http://localhost:22687" />
    <add key="allowedCorsMethods" value="get, post, put, delete, options, batch" />
    <add key="allowedCorsHeaders" value="*" />
  </appSettings>
...
</configuration>

Причина цикла поиска допустимых источников заключается в том, что вы не можете ответить списком разрешенных источников...

Это решило большинство проблем за одним исключением (если я правильно помню, были проблемы с глаголами PUT и DELETE). Это потребовало удаления «ExtensionlessUrlHandler-Integrated-4.0» и повторного добавления его с путем и глаголом в разделе обработчиков файла web.config.

web.config (второе изменение)

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

Полезные ссылки, связанные с CORS

person RonnBlack    schedule 21.06.2016
comment
Вы должны принять свой ответ, чтобы закрыть вопрос. Тем временем Microsoft позже поставила модуль IIS CORS для таких, docs.microsoft.com/en-us/iis/extensions/cors-module/ - person Lex Li; 03.09.2018

Это не тот IdentityServer, который вы используете, но это может быть та же проблема. Что касается страницы Github IdentityServer, вам необходимо активировать RAMMFAR ( runAllManagedModulesForAllRequests) для вашего приложения при работе под IIS.

<system.webServer>
  <modules runAllManagedModulesForAllRequests="true">
  </modules>
</system.webServer>
person Hypnobrew    schedule 20.04.2016

У меня была такая же проблема, я сделал все, как предложил мистер Том Холл. Но все же хром сообщил об отсутствии заголовка Access-control-allow-origin. После проверки с помощью fidler я понял, что мой запрос проходит через прокси-сервер, и мой прокси-сервер обрабатывает запрос параметров предварительной проверки.

Итак, в "параметрах интернета" я удалил прокси-сервер и обнаружил, что все работает...!!!

person Pradeep    schedule 03.11.2016