web-dev-qa-db-ja.com

IIS Windows認証が有効な場合のCORS要求に対する401応答

WebAPIプロジェクトでCORSサポートを有効にしようとしています。匿名認証を有効にするとすべてが正常に動作しますが、Windows Auth +匿名認証を無効にすると、送信されたOPTIONSリクエストは常に401不正な応答を返します。それを要求するサイトはドメイン上にあるため、電話をかけることができますが、Windows認証を無効にせずに問題を回避する方法はありますか?

37
dariusriggins

MSから:

匿名認証を無効にすると、IISはすべてのリクエストに401を返します。Windows認証を有効にしている場合、その場合の401応答にはWWW-Authenticateヘッダーが含まれます。クライアントが認証ハンドシェイクを開始すると、問題は、顧客が使用しているクライアントがWindows認証を実行できるかどうかになります。

最後に、1つの動詞(この場合はOPTIONS)に対して匿名アクセスを許可し、他の動詞にはWindows認証を要求するようにURLを構成することが可能かどうかについて、根本的な疑問があるようです。 IISは、単純な構成ではこれをサポートしません。匿名認証とWindows認証の両方を有効にし、匿名ユーザーへのアクセスを拒否するコンテンツにACLを設定し、構成することにより、 URLに関連付けられたファイルの存在を確認しないように、問題のURLのハンドラーマッピング。

14
dariusriggins

匿名ユーザーにはOPTIONS動詞のみを許可できます。

<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

37
Jan Remunda

数年後、@ 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は実際には許可されたホストのリストで検索されますが、それは単なる複雑なことです。これは、他のすべてのリクエストが検証されますが、オプションが返されるだけであることを意味します。

この質問をありがとう、私はそれなしで失われていたでしょう!

22
Stu

これを修正する最も簡単な方法は、request_method = ^ OPTIONS $という条件で書き換えルールを作成することです。次に、アクションをカスタム応答に設定し、200 OKに設定します。その後、すべてのオプション要求は401ではなく200で応答します。これにより、CORSの問題が修正されます。

もちろん、正しいクロスオリジンリクエストヘッダーがあることを確認する必要があります。

これにより、統合認証が有効な場合に401で応答するオプションリクエスト(資格情報を持たない)が停止します。

4
Luke Basil

受け入れられた答えは正しいですが、「iisnodeおよびnpm corsモジュールを使用したノード」セットアップでREST APIをトラブルシューティングし、すべてのユーザーに対して匿名認証を有効にするだけでは不安でした。そのノードアプリケーションなので、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>
4
mrplatina

IE 10および11 のバグが原因で今日同じ問題に遭遇しました。WebApiの代わりにServiceStackを使用していますが、このアプローチも同様に機能します。

  1. IIS WebサイトでWindows統合認証と匿名認証を有効にしました。
  2. ServiceStack Pipelineに一連のフィルターがあります。
    • CorsおよびOPTIONSリクエストを処理するには、オプションリクエストで、必要なヘッダーを追加してリクエストを終了します。
    • HttpRequestが認証されているかどうかをチェックするためのフィルター?、
    • などフィルター、

すべてのフィルターを通過した後、サービスを実行します。

CorsFeature.cs

AuthenticateFilter

私のAppHostでは、

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

appHost.RequestFilters.Add(AuthenticateFilter.Authenticate);

CorsFeatureを変更して、ヘッダーの追加に加えて、OptionsRequestを処理し、認証された要求を確認するための認証フィルターを追加しました。

3
Sathish Naga

関連質問:IIS CORS Preflight OPTIONS要求をハイジャックします

複数の場所で見つかった回答から情報をマージします。イントラネットでWindows認証を使用してASP.netページメソッドでCORSを有効にする必要がある場合、これが機能しているようです。 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>
3
Shiroy

私はこれがいくつかの可能な解決策(および他の質問)を持つ古い質問であることを理解していますが、他の誰かがこれに遭遇した場合、IIS CORS 1.0は17年11月現在利用可能です:

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

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

IIS Windows Platform Installer(WPI)からダウンロードできます。これにより、CORS認証の問題の多くが解決されます。

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の詳細情報-> https://docs.Microsoft.com/en-us/aspnet/aspnet/overview/owin-and-katana/owin-middleware-in-the-iis-integrated-pipeline

また、許可されたヘッダーを明示的に定義する必要があることも重要です。 _*_をプレースホルダーとして使用すると失敗します。

たぶんそれは誰かを助ける。

1
Arikael

私にとってうまくいったのは(AngularJSまたはJQueryで作業しているとき)、withCredentials:trueをクライアント上の各リクエストに追加することです:

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

サーバーでCORSを有効にし、nugetのMicrosoft.Owin.Corsを使用してこれを行い、以下のようにStartupに追加しました。

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

        ConfigureOAuth(app);

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

    }

参照:

0
Philip Patrick

@dariusrigginsによって提供される答えを拡張します。この投稿を確認してください: Microsoft |開発者:すべてをまとめる– CORSチュートリアル

IIS構成:

認可ルール

Authorization rule

承認段階(または承認イベント)では、CORSプリフライトからの匿名要求のみを許可し、他のすべての受信要求には認証資格情報が必要であることを確認する必要があります。これは認可ルールを介して実現できます。すべてのユーザーにサイトへのアクセスを許可する既定の承認規則は既に配置されており、既定でIISによって提供されます。 OPTIONS http動詞を使用しているリクエストを送信する場合、匿名ユーザーのみを許可するようにこのルールを変更することから始めます。以下は、この許可ルールのIISのターゲット構成です。

承認ルールを編集

Edit Authorization rule

0
SubodhW