Вопрос по – 401 ответ на запрос CORS в IIS с включенной аутентификацией Windows

36

Я пытаюсь включить поддержку CORS в своем проекте WebAPI, и если я включаю анонимную аутентификацию, то все работает нормально, но при отключенной анонимной аутентификации Windows Auth + отправленный запрос OPTIONS всегда возвращает 401 неавторизованный ответ. Сайт, запрашивающий его, находится на DOMAIN, поэтому должен быть в состоянии сделать звонок, есть ли способ обойти проблему без отключения проверки подлинности Windows?

Да, работает на W7 Ultimate & amp; также на Server 2008. Я вставлю в ответ, полученный от MS, это кажется возможным, просто непросто, но вместо этого мы собираемся перейти к более oauth-стилю и отделить наш API, чтобы разрешить анонимную аутентификацию, но выпустить токены для авторизации. dariusriggins
Вы проверили, действительно ли встроенная проверка подлинности Windows поддерживается на вашем компьютере?http://technet.microsoft.com/en-us/library/cc754628%28v=WS.10%29.aspx Artem Oboturov

Ваш Ответ

11   ответов
2

Связанный вопрос: IIS угоняет запрос CORS Preflight OPTIONS

Слияние информации из ответов, найденных в нескольких местах. Если вам нужно включить CORS для метода страницы ASP.net с проверкой подлинности Windows в интрасети, это то, что, кажется, работает. Без измененийweb.configэто не работает.

Вы должны добавить это кGlobal.asax

    protected void Application_BeginRequest(object sender, EventArgs e)
    {
        string httpOrigin = HttpContext.Current.Request.Params["HTTP_ORIGIN"] ?? HttpContext.Current.Request.Params["ORIGIN"] ?? "*";
        HttpContext.Current.Response.AddHeader("Access-Control-Allow-Origin", httpOrigin);
        HttpContext.Current.Response.AddHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS");
        HttpContext.Current.Response.AddHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept, X-Token");
        HttpContext.Current.Response.AddHeader("Access-Control-Allow-Credentials", "true");

        if (HttpContext.Current.Request.HttpMethod == "OPTIONS")
        {
            HttpContext.Current.Response.StatusCode = 200;
            var httpApplication = sender as HttpApplication;
            httpApplication.CompleteRequest();
        }
    }

И это кweb.config

 <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>
1

Я использую Web API и OWIN и попробовал все предложенные решения, но единственное, что сработало, это следующее

//use it in your startup class
app.Use((context, next) =>
{
    if (context.Request.Headers.Any(k => k.Key.Contains("Origin")) && context.Request.Method == "OPTIONS")
    {
        context.Response.StatusCode = 200;
        context.Response.Headers.Add("Access-Control-Allow-Origin", new string[1] { "ALLOWED_ORIGIN" });
        context.Response.Headers.Add("Access-Control-Allow-Headers", new string[4] { "Origin", "X-Requested-With", "Content-Type", "Accept" });
        context.Response.Headers.Add("Access-Control-Allow-Methods", new string[5] { "GET", "POST", "PUT", "DELETE", "OPTIONS" });
        context.Response.Headers.Add("Access-Control-Allow-Credentials", new string[1] { "true" });

        return context.Response.WriteAsync("");
    }

    return next.Invoke();
});

//this is important! Without it, it didn't work (probably because the middleware was too late)
app.UseStageMarker(PipelineStage.Authenticate);

вам нужно вставить этот код где-нибудь в один из ваших классов запуска OWIN. Важно позвонитьapp.UseStageMarker(PipelineStage.Authenticate) потому что иначе предпечатная проверка не удалась. Дополнительная информация для UseStageMarker - & gt;https://docs.microsoft.com/en-us/aspnet/aspnet/overview/owin-and-katana/owin-middleware-in-the-iis-integrated-pipeline

Также важно, что вам необходимо явно определить разрешенные заголовки. Это не удастся, если вы используете* в качестве заполнителя.

Может быть, это кому-нибудь поможет.

4

Принятый ответ правильный, однако я устранял неполадки API-интерфейса rest с «узлом с модулем iisnode и npm cors». настройка на некоторое время и не было достаточно просто включить анонимную аутентификацию для всех пользователей. Поскольку это приложение узла, тег system.web мало что делает. Я закончил со следующим дополнением к web.config:

<system.webServer>
<security>
  <requestFiltering>
    <hiddenSegments>
      <add segment="node_modules" />
    </hiddenSegments>
  </requestFiltering>
  <authorization>
    <add accessType="Allow" verbs="OPTIONS" users="?" />
    <add accessType="Deny" verbs="GET, PUT, POST, DELETE" users="?" />
  </authorization>
</security>
</system.webServer>
& quot; Работал для меня & quot; в IIS + Basic Auth, которая имеет ту же проблему:}
Это решение работало для нас в IIS 10 Win 2016. Убедитесь, что роль / функция URL-авторизации установлена как часть безопасности IIS! В противном случае это правило не будет реализовано.
1

Я понимаю, что это старый вопрос с несколькими возможными решениями (а также с другими вопросами), но в случае, если кто-то еще сталкивается с этим, IIS CORS 1.0 доступен с ноября 17:

https://blogs.iis.net/iisteam/introducing-iis-cors-1-0

https://docs.microsoft.com/en-us/iis/extensions/cors-module/cors-module-configuration-reference

Вы можете скачать его с помощью IIS Windows Platform Installer (WPI). Это должно решить многие из ваших проблем с аутентификацией CORS. Наслаждайтесь!

отличный! Я использовал следующий CORS-config в моем файле web.config:<cors enabled="true"> <add origin="http://192.168.3.253:5001" allowCredentials="true" maxAge="120"> <allowHeaders allowAllRequestedHeaders="true" /> <allowMethods> <add method="GET" /> <add method="HEAD" /> <add method="POST" /> <add method="PUT" /> <add method="DELETE" /> </allowMethods> </add> </cors>
20

Спустя несколько лет, но благодаря ответам @dariusriggins и @ lex-li мне удалось добавить следующий код в мой Global.asax:

    public void Application_BeginRequest(object sender, EventArgs e)
    {
        string httpOrigin = Request.Params["HTTP_ORIGIN"];
        if (httpOrigin == null) httpOrigin = "*";
        HttpContext.Current.Response.AddHeader("Access-Control-Allow-Origin", httpOrigin);
        HttpContext.Current.Response.AddHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS");
        HttpContext.Current.Response.AddHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept, X-Token");
        HttpContext.Current.Response.AddHeader("Access-Control-Allow-Credentials", "true");

        if (Request.HttpMethod == "OPTIONS")
        {
            HttpContext.Current.Response.StatusCode = 200;
            var httpApplication = sender as HttpApplication;
            httpApplication.CompleteRequest();
        }
    }

httpOrigin на самом деле ищется в списке разрешенных хостов, но это просто сложные вещи. Это означает, что все остальные запросы проверяются, а параметры просто возвращаются.

Спасибо за этот вопрос, я бы потерялся без него!

Создан новый ответ с более подробной информацией ниже ...
Я пробовал много разных способов включить CORS с WebAPI, работающим на IIS для клиента Angular 2, включая добавление его в web.config, аннотации данных о действиях моего контроллера и вызов "EnableCors" в WebApiConfig.Register. Это решение являетсяonly one которая фактически работала с проверкой подлинности Windows (NTLM), а также следила за тем, чтобы HTTP-клиент Angular 2 отправлялwithCredentials в заголовке HTTP. Спасибо!
Это великолепно! Работает как шарм! Вам даже не нужно помещать его в Application_BeginRequest. Вы даже можете поместить его в свою загрузку страницы, если это всего лишь одна страница, которую вы хотите разрешить.
-1

Включение SupportCredentials на EnableCorsAttribute в WebApiConfig.cs помогло мне:

public static void Register(HttpConfiguration config)
{        
    //enable cors request just from localhost:15136 
    var cors = new EnableCorsAttribute("http://localhost:15136", "*", "*");
    cors.SupportsCredentials = true;
    config.EnableCors(cors);

    //other stuff
}

https://www.asp.net/web-api/overview/security/enabling-cross-origin-requests-in-web-api

Убедитесь, что вы отправляете учетные данные при звонке из JavaScript ({withCredentials :true})

Я пытаюсь сделать то же самое, но без учетных данных. Не повезло даже с анонимным авторизацией на
Это не работает в Chrome. Я использую withCredentials = true, и предварительный запрос OPTIONS все еще не отправляет учетные данные.
0

Что работало для меня (при работе с AngularJS или JQuery), так это добавление withCredentials: true к каждому запросу клиента:

$http.get("http://localhost:88/api/tests", {withCredentials :true})

И включив CORS на сервере, это было сделано с помощью Microsoft.Owin.Cors из nuget и добавлено в автозагрузку, как показано ниже:

public void Configuration(IAppBuilder app)
    {
        HttpConfiguration config = new HttpConfiguration();

        ConfigureOAuth(app);

        WebApiConfig.Register(config);
        app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll);
        app.UseWebApi(config);

    }

Рекомендации:

3

Я столкнулся с той же проблемой сегодня из-за ошибки вIE 10 и 11Я использую ServiceStack вместо WebApi, но этот подход может работать и для вас.

  1. Enabled Windows Integrated and Anonymous Authentication on IIS Web Site.
  2. Have a series of filters on the ServiceStack Pipeline,
    • For handling Cors and OPTIONS request, On Options request, I add necessary headers and end the request,
    • Filter for checking includng HttpRequest is Authenticated?,
    • etc filter,

После прохождения всех фильтров, он выполняет сервис.

CorsFeature.cs

AuthenticateFilter

В моем AppHost,

appHost.Plugins.Add(new CorsFeature());

appHost.RequestFilters.Add(AuthenticateFilter.Authenticate);

Я изменил CorsFeature для обработки OptionsRequest в дополнение к добавлению заголовков, фильтра проверки подлинности для проверки подлинности запросов!

Я пропускаю проверку аутентификации пользователя для запросов OPTIONS. Я добавлю пример кода.
Привет, можешь рассказать немного подробнее о том, что ты сделал? Я сталкиваюсь с подобными проблемами, а также использую ServiceStack, который развернут через SharePoint 2013
36

Вы можете разрешить только глагол ОПЦИИ для анонимных пользователей.

<system.web>
  <authentication mode="Windows" />
    <authorization>
      <allow verbs="OPTIONS" users="*"/>
      <deny users="?" />
  </authorization>
</system.web>

В соответствии со спецификациями W3C браузер исключает учетные данные пользователя из предварительной проверки CORS:https://dvcs.w3.org/hg/cors/raw-file/tip/Overview.html#preflight-request

Это не работает!
Видимо да. & quot; Анонимная аутентификация предоставляет пользователям доступ к публичным областям вашего веб-сайта или FTP-сайта без запроса имени пользователя или пароля. & quot;bit.ly/1wjLdO9
Похоже на аккуратное решение. Теперь, как мне настроить эту конфигурацию для ядра asp.net?
Это должен быть принятый ответ.
Требуется ли для этого анонимный модуль авторизации, включенный в IIS?
4

Самый простой способ исправить это - создать правило перезаписи с условием request_method = ^ OPTIONS $. Затем установите действие как пользовательский ответ, установите его на 200 ОК. Тогда все запросы опций будут отвечать 200 вместо 401. Это решит проблему с CORS.

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

Это остановит запросы опций (у которых нет никаких учетных данных), отвечающих 401, когда интегрированная аутентификация включена.

Видите ли вы какие-либо потенциальные проблемы безопасности с этим?
13

От MS:

Если вы отключите анонимную аутентификацию, то по замыслу IIS вернет 401 для любого запроса. Если бы они включили аутентификацию Windows, ответ 401 в этом случае имел бы заголовок WWW-Authenticate, чтобы позволить клиенту запустить аутентификацию. Тогда возникает вопрос, может ли клиент, который использует клиент, выполнить проверку подлинности Windows или нет.

Наконец, может показаться, что может возникнуть основной вопрос о том, возможно или нет настроить URL-адрес таким образом, чтобы анонимный доступ был разрешен для одного глагола (в данном случае - ОПЦИИ), но для других глаголов требуется проверка подлинности Windows. IIS не поддерживает это через простую настройку. Такое поведение может быть возможно, включив анонимную проверку подлинности и проверку подлинности Windows, установив списки ACL для содержимого, запрещающего доступ анонимному пользователю, а затем настроив сопоставление обработчика для рассматриваемого URL-адреса, чтобы он не проверял существование файл, связанный с URL. Но потребовалось бы немного поиграть с этим, чтобы подтвердить это.

Просто заметил, что многие парни сталкивались с ошибками 401, когда их веб-API защищен аутентификацией Windows или чем-то подобным. Предварительные запросы CORS не содержат учетных данных, поэтому IIS ответит 401.2 даже до того, как ASP.NET коснется их. Грязный обходной путь - написать модуль HTTP и подключиться к конвейеру IIS, который регистрируется наHttpApplication.BeginRequest Событие, при котором этот модуль возвращает ожидаемый ответ 200 на запросы предполетной проверки. Этот обходной путь применяется только к интегрированному режиму IIS 7+. К сожалению, служба поддержки Microsoft может не знать об этом совете.
@ThiagoSilva, я только что обновил пост, чтобы указать, какую статью вы должны прочитать.developer.mozilla.org/en-US/docs,/Web/HTTP/… содержит даже примеры запросов / ответов, так что вы можете легко следовать.
Только что сделал пост в блоге,blog.lextudio.com/2014/11/… с дополнительной информацией о IIS 6 и классическом режиме пользователей.
@LexLi прочитал ваш блог, но, к сожалению, вы не детализируете точную реализацию события BeginRequest, поэтому я не совсем понимаю, что все включить в ответ 200 (например, заголовки и т. Д.). Я понимаю, как создавать HttpModules, просто хотел бы уточнить, что ответить на запрос предполетной проверки.
@ lex-li: я только что опубликовал ответ, использующий только global.asax, к которому я не смог бы приблизиться без вашей статьи в блоге. Спасибо!

Похожие вопросы