ASP.Net MVCでAccess-Control-Allow-Originを設定する-最も簡単な方法


206

いくつかのjsonを返す単純なアクションメソッドがあります。ajax.example.comで実行されます。別のサイトsomeothersite.comからアクセスする必要があります。

私がそれを呼び出そうとすると、期待どおりの結果が得られます...:

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

私はこれを回避する2つの方法を知っています:JSONPカスタムHttpHandlerの作成ヘッダーを設定します。

より簡単な方法はありませんか?

単純なアクションで許可されたオリジンのリストを定義すること、または単純に全員に許可することは不可能ですか?たぶんアクションフィルター?

最適なのは...:

return json(mydata, JsonBehaviour.IDontCareWhoAccessesMe);

1
vNextとMVC6のためのこちらをご覧ください:neelbhatt40.wordpress.com/2015/09/10/...
ニール

回答:


382

プレーン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?");
}

ASP.NET Web APIの場合

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を使用してダウンロードし、付属の指示に​​従ってください。

ブログ投稿 | ソースコード


8
すごい!私はMVC + Uを愛しています!
Piotr Kula、2012年

2
このソリューションの優雅さに畏敬の念を抱く
BraveNewMath

3
CORSを独自のドメインに制限する場合は、特定のオリジンを受け入れるように属性を簡単に拡張できます。
ペトルスセロン

2
これをApp_Start \ FilterConfigのRegisterHttpFiltersに追加できますか?そうすることで、プロジェクトのすべてのAPIコントローラーに適用されます。これを上記のパテのコメントと組み合わせると、すべてのコントローラーのCORSをドメインに制限できます。
bdwakefield 2013年

9
私は最近、プロジェクトをMVC 5に更新し、これを試みました。フィルターにヘッダーを追加しても機能しないようです。ネットワークで要求を表示すると、応答にヘッダーがありません。これを機能させるために他に必要なことはありますか?
Kneemin

121

IIS 7以降を使用している場合は、web.configファイルをフォルダーのルートに配置できます。これをsystem.webServerセクションに追加します。

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

参照:http : //msdn.microsoft.com/en-us/library/ms178685.aspx および:http : //enable-cors.org/#how-iis7


1
理由はもう思い出せませんが、この方法はIIS 7以降で常に機能するとは限りません
LaundroMatt

うーん。これが機能しないと私が思う唯一の理由は、リクエストがCORS以外のブラウザからのものである場合です。しかし、私は調査を続けます。
2013年

29
また、これによりウェブサイト全体がCORSにとって使いやすくなります。誰かがCORSフレンドリとして単一のアクションまたはコントローラーのみをマークしたい場合、受け入れられた答えははるかに優れています。
Lev Dubinets 2013

1
ASP.Netセクションが表示される場合は、ヒントがあります。「注:このアプローチは、IIS6、IIS7クラシックモード、およびIIS7統合モードと互換性があります。」
percebus 2013

1
SharePoint環境でアプリを公開すると、クロスドメインの問題が発生します。ローカル環境でアプリを実行すると、アプリは正常に動作しますが、azureでSharePointサイトに公開すると、Ajax.Beginフォーム呼び出しのエラーページにリダイレクトされます。この解決策を試しましたが、うまくいきません。他に何か他の方法はありますか?
Jyotsna Wadhwani 2017

22

リクエストがcookieで渡されたときにブラウザが取得したコンテンツの提供をブラウザが拒否し(たとえば、xhrにがあったwithCredentials=true)、サイトがにAccess-Control-Allow-Origin設定されているという問題に遭遇しました*。(Chromeのエラーは、「認証情報フラグがtrueの場合、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);
    }
}

これは特に役に立ちました。ありがとうございました。
cklimowski

15

これは本当に簡単です、これをweb.configに追加するだけです

<system.webServer>
  <httpProtocol>
    <customHeaders>
      <add name="Access-Control-Allow-Origin" value="http://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では、Webサーバーにアクセスできるすべてのドメインを配置し、ヘッダーには、任意のajax httpリクエストが使用できるすべての可能なヘッダーを配置し、メソッドでは、サーバーで許可するすべてのメソッドを配置します

よろしくお願いします:)


承認されたクエリを使用する場合は、Access-Control-Allow-Headersに「承認」を追加すると便利です。
AFract

9

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でwebservice / controllerヘッダーを更新します

// GET api/Master/Sync/?version=12121
        [HttpGet][HttpOptions]
        public dynamic Sync(string version) 
        {

ところで、サイトフィニティでは、セキュリティセクションのシステムの詳細設定に*を追加する必要があります
Bishoy Hanna

コントローラヘッダーを更新する必要があるファイルはどれですか。
user3281466 2014年


5

APIを使用している場合は、この行をメソッドに追加します。

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

4

このチュートリアルは非常に役立ちます。簡単に要約すると:

  1. Nugetで利用可能なCORSパッケージを使用します。 Install-Package Microsoft.AspNet.WebApi.Cors

  2. あなたにはWebApiConfig.cs、ファイル、追加config.EnableCors()するRegister()方法。

  3. corsを処理するために必要なコントローラーに属性を追加します。

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


リクエストにカスタムヘッダーを設定する必要があり、カスタム属性メソッドがブラウザーのプリフライトリクエストで機能しなかったため、このメソッドを使用する必要がありました。これはすべてのケースで機能するようです。
lehn0058 2016

3
    public ActionResult ActionName(string ReqParam1, string ReqParam2, string ReqParam3, string ReqParam4)
    {
        this.ControllerContext.HttpContext.Response.Headers.Add("Access-Control-Allow-Origin","*");
         /*
                --Your code goes here --
         */
        return Json(new { ReturnData= "Data to be returned", Success=true }, JsonRequestBehavior.AllowGet);
    }

2

Access-Control-Expose-Headersを渡す方法はいくつかあります。

  • jgauffinが説明したように、新しい属性を作成できます。
  • LaundroMattで説明したように、web.configファイルに追加できます。
  • もう1つの方法は、以下のようにwebApiconfig.csファイルにコードを追加することです。

    config.EnableCors(new EnableCorsAttribute( " "、headers: " "、methods: "*"、exposedHeaders: "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", "http://localhost:4200");
                HttpContext.Current.Response.AddHeader("Access-Control-Expose-Headers", "TestHeaderToExpose");
                HttpContext.Current.Response.End();
            }
        }

オプションのために書きました。必要に応じて変更してください。

ハッピーコーディング!!


1

一晩中苦労した後、ようやくこれを機能させることができました。デバッグ後、私が調べていた問題は、クライアントがいわゆるプリフライトオプション要求を送信して、アプリケーションが提供されたオリジン、メソッド、およびヘッダーを使用してポスト要求を送信できるかどうかを確認することでした。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アクションメソッドは次のようになります。ここで重要なのは、Options HttpVerbsについても言及することです。そうしないと、プリフライト要求が失敗します。

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

0

Web.configに次のように入力します

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

0

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="http://*" allowed="false" />
        </cors>
    </system.webServer>

0

私はDotNet Core MVCを使用しており、nugetパッケージ、Startup.cs、属性、およびこの場所で数時間戦った後、これをMVCアクションに単に追加しました。

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

これはかなりぎこちないことに気づきましたが、それだけで十分であり、他のヘッダーを追加したくなかったのです。これが誰かを助けることを願っています!

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.