複数のドメインを持つアクセス制御許可元


97

私のweb.configで、access-control-allow-originディレクティブに複数のドメインを指定したいと思います。使いたくない*。私はこの構文を試しました:

<add name="Access-Control-Allow-Origin" value="http://localhost:1506, http://localhost:1502" />

これです

<add name="Access-Control-Allow-Origin" value="http://localhost:1506 http://localhost:1502" />

これです

<add name="Access-Control-Allow-Origin" value="http://localhost:1506; http://localhost:1502" />

そしてこれ

<add name="Access-Control-Allow-Origin" value="http://localhost:1506" />
<add name="Access-Control-Allow-Origin" value="http://localhost:1502" />

しかし、どれも機能しません。正しい構文は何ですか?

回答:


77

Access-Control-Allow-Origin応答ヘッダーは1つしか存在できず、そのヘッダーは起点値を1つしか持てません。したがって、これを機能させるには、次のようなコードが必要です。

  1. Originリクエストヘッダーを取得します。
  2. 元の値がホワイトリストに登録された値の1つであるかどうかを確認します。
  3. 有効な場合、Access-Control-Allow-Originヘッダーにその値を設定します。

これをweb.configだけで行う方法はないと思います。

if (ValidateRequest()) {
    Response.Headers.Remove("Access-Control-Allow-Origin");
    Response.AddHeader("Access-Control-Allow-Origin", Request.UrlReferrer.GetLeftPart(UriPartial.Authority));

    Response.Headers.Remove("Access-Control-Allow-Credentials");
    Response.AddHeader("Access-Control-Allow-Credentials", "true");

    Response.Headers.Remove("Access-Control-Allow-Methods");
    Response.AddHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS");
}

2
それが私の質問に答えます。なぜマイクロソフトがweb.configで複数のオリジンを指定することを許可していないのかわかりません...
Sam

17
このコードはどこに追加できますか?サーバーによって生成され、AJAX経由で読み取られるプレーンテキストファイルがあり、コードはまったくありません。ディレクトリ内のテキストファイルへのアクセスを制限するコードをどこに配置できますか?
ハリー

3
@Simon_Weaverには、*任意のオリジンがリソースにアクセスできるようにする値があります。ただし、元の質問は、一連のドメインのホワイトリスト登録について尋ねていました。
monsur 2015

2
私はasp .netを初めて使用するので、このコードをasp .net Web APIプロジェクトのどこに配置すればよいですか?
アムリット2018年

91

IIS 7.5以降およびRewrite 2.0の場合は、次を使用できます。

<system.webServer>
   <httpProtocol>
     <customHeaders>
         <add name="Access-Control-Allow-Headers" value="Origin, X-Requested-With, Content-Type, Accept" />
         <add name="Access-Control-Allow-Methods" value="POST,GET,OPTIONS,PUT,DELETE" />
     </customHeaders>
   </httpProtocol>
        <rewrite>            
            <outboundRules>
                <clear />                
                <rule name="AddCrossDomainHeader">
                    <match serverVariable="RESPONSE_Access_Control_Allow_Origin" pattern=".*" />
                    <conditions logicalGrouping="MatchAll" trackAllCaptures="true">
                        <add input="{HTTP_ORIGIN}" pattern="(http(s)?://((.+\.)?domain1\.com|(.+\.)?domain2\.com|(.+\.)?domain3\.com))" />
                    </conditions>
                    <action type="Rewrite" value="{C:0}" />
                </rule>           
            </outboundRules>
        </rewrite>
 </system.webServer>

サーバー変数RESPONSE_Access_Control_Allow_Origin部分の説明:
Rewriteでは、その後に任意の文字列を使用できRESPONSE_、残りの単語をヘッダー名として使用して応答ヘッダーを作成します(この場合はAccess-Control-Allow-Origin)。書き換えでは、ダッシュ「-」の代わりにアンダースコア「_」を使用します(書き換えにより、ダッシュに変換されます)

サーバー変数の説明HTTP_ORIGIN
同様に、Rewrite HTTP_では、プレフィックスとして使用して任意のリクエストヘッダーを取得できます。ダッシュと同じルール(ダッシュ「-」の代わりにアンダースコア「_」を使用)。


これがIIS 7.5で機能しない理由を考えられますか?
Phil Ricketts、2015

うまくいくと思います。IIS 8.5をテストしたのは、このバージョンを指定したからです。
Paco Zarate、2015

4
@PacoZarate素敵なヒント、素晴らしいヒント。正規表現を簡略化し、より一般的にするには、-を使用できます(http(s)?:\/\/((.+\.)?(domain1|domain2)\.(com|org|net)))。そうすれば、他のドメインをかなり簡単に追加でき、複数のトップレベルドメイン(com、org、netなど)をサポートできます。
マーリン

4
IIS 7.5でこれを試しました。うまく機能しているようです。
Prescient、2015年

2
キャッシュに問題がありますか?web.configを調整した後、最初にアクセスしたWebサイトはうまく一致しますが、2番目のWebサイトは最初のWebサイトと同じヘッダーを返します。したがって、ドメインが一致しすぎないようにします。
Airn5475 2018年

20

Web.APIでは、この属性はhttp://www.asp.net/web-api/overview/security/enabling-cross-origin-requests-in-web-apiでMicrosoft.AspNet.WebApi.Cors詳しく説明されているように使用して追加できます

MVCでは、フィルター属性を作成して、この作業を行うことができます。

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method,
                AllowMultiple = true, Inherited = true)]
public class EnableCorsAttribute : FilterAttribute, IActionFilter {
    private const string IncomingOriginHeader = "Origin";
    private const string OutgoingOriginHeader = "Access-Control-Allow-Origin";
    private const string OutgoingMethodsHeader = "Access-Control-Allow-Methods";
    private const string OutgoingAgeHeader = "Access-Control-Max-Age";

    public void OnActionExecuted(ActionExecutedContext filterContext) {
        // Do nothing
    }

    public void OnActionExecuting(ActionExecutingContext filterContext)
    {
        var isLocal = filterContext.HttpContext.Request.IsLocal;
        var originHeader = 
             filterContext.HttpContext.Request.Headers.Get(IncomingOriginHeader);
        var response = filterContext.HttpContext.Response;

        if (!String.IsNullOrWhiteSpace(originHeader) &&
            (isLocal || IsAllowedOrigin(originHeader))) {
            response.AddHeader(OutgoingOriginHeader, originHeader);
            response.AddHeader(OutgoingMethodsHeader, "GET,POST,OPTIONS");
            response.AddHeader(OutgoingAgeHeader, "3600");
        }
    }

    protected bool IsAllowedOrigin(string origin) {
        // ** replace with your own logic to check the origin header
        return true;
    }
}

次に、特定のアクション/コントローラーに対してそれを有効にします。

[EnableCors]
public class SecurityController : Controller {
    // *snip*
    [EnableCors]
    public ActionResult SignIn(Guid key, string email, string password) {

または、Global.asax.csのすべてのコントローラーに追加します

protected void Application_Start() {
    // *Snip* any existing code

    // Register global filter
    GlobalFilters.Filters.Add(new EnableCorsAttribute());
    RegisterGlobalFilters(GlobalFilters.Filters);

    // *snip* existing code
}

これが機能する.Net / MVCのバージョンを知っていますか?
Keab42

私はこれを.net 4 / MVC 3で正常に使用しています-私がそれをより高いバージョンで機能するはずである限り私が知っている限り、それ以降のMVCバージョンでグローバルフィルターを登録する好ましい方法があるかもしれません。
ロブ教会

WEB API 2ソリューションのみに注意してください。WEB API 1は対象外
Samih A

5

すべての答えを読んで試した後、どれも私を助けませんでした。他の場所を検索しているときに見つけたのは、コントローラーに追加できるカスタム属性を作成できることです。EnableCorsを上書きし、ホワイトリストに登録されたドメインを追加します。

このソリューションは、コントローラーのEnableCors属性でドメインをハードコードするのではなく、webconfig(appsettings)でホワイトリストに登録されたドメインを持つことができるため、うまく機能しています。

 [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false)]
public class EnableCorsByAppSettingAttribute : Attribute, ICorsPolicyProvider
{
    const string defaultKey = "whiteListDomainCors";
    private readonly string rawOrigins;
    private CorsPolicy corsPolicy;

    /// <summary>
    /// By default uses "cors:AllowedOrigins" AppSetting key
    /// </summary>
    public EnableCorsByAppSettingAttribute()
        : this(defaultKey) // Use default AppSetting key
    {
    }

    /// <summary>
    /// Enables Cross Origin
    /// </summary>
    /// <param name="appSettingKey">AppSetting key that defines valid origins</param>
    public EnableCorsByAppSettingAttribute(string appSettingKey)
    {
        // Collect comma separated origins
        this.rawOrigins = AppSettings.whiteListDomainCors;
        this.BuildCorsPolicy();
    }

    /// <summary>
    /// Build Cors policy
    /// </summary>
    private void BuildCorsPolicy()
    {
        bool allowAnyHeader = String.IsNullOrEmpty(this.Headers) || this.Headers == "*";
        bool allowAnyMethod = String.IsNullOrEmpty(this.Methods) || this.Methods == "*";

        this.corsPolicy = new CorsPolicy
        {
            AllowAnyHeader = allowAnyHeader,
            AllowAnyMethod = allowAnyMethod,
        };

        // Add origins from app setting value
        this.corsPolicy.Origins.AddCommaSeperatedValues(this.rawOrigins);
        this.corsPolicy.Headers.AddCommaSeperatedValues(this.Headers);
        this.corsPolicy.Methods.AddCommaSeperatedValues(this.Methods);
    }

    public string Headers { get; set; }
    public string Methods { get; set; }

    public Task<CorsPolicy> GetCorsPolicyAsync(HttpRequestMessage request,
                                               CancellationToken cancellationToken)
    {
        return Task.FromResult(this.corsPolicy);
    }
}

    internal static class CollectionExtensions
{
    public static void AddCommaSeperatedValues(this ICollection<string> current, string raw)
    {
        if (current == null)
        {
            return;
        }

        var paths = new List<string>(AppSettings.whiteListDomainCors.Split(new char[] { ',' }));
        foreach (var value in paths)
        {
            current.Add(value);
        }
    }
}

私はこのガイドをオンラインで見つけました、そしてそれは魅力のように働きました:

http://jnye.co/Posts/2032/dynamic-cors-origins-from-appsettings-using-web-api-2-2-cross-origin-support

困っている人のためにここに置いておきます。


これはリンクのみの回答です。代わりにそれ自体で答えを立ててください。
モニカ

1
わかりました、私はここに新しいです。
Helpha 2016年

3

「monsur」からのアドバイスに従って、リクエスト処理コードでこれをなんとか解決しました。

string origin = WebOperationContext.Current.IncomingRequest.Headers.Get("Origin");

WebOperationContext.Current.OutgoingResponse.Headers.Add("Access-Control-Allow-Origin", origin);

これは、たとえばWebフォームで行う方法です。可能な場合は、単にRequest.Headersを使用してください。また、必要に応じて、ホワイトリストを使用して許可されたドメインのみをフィルタリングします。
AFract

3
これは、web.configファイルに<add name = "Access-Control-Allow-Origin" value = "*" />を
追加するのと同じ

3

IIS 7.5以降の場合、IIS CORSモジュールを使用できます:https ://www.iis.net/downloads/microsoft/iis-cors-module

web.configは次のようになります。

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <system.webServer>
        <cors enabled="true" failUnlistedOrigins="true">
            <add origin="http://localhost:1506">
                <allowMethods>                    
                    <add method="GET" />
                    <add method="HEAD" />
                    <add method="POST" />
                    <add method="PUT" /> 
                    <add method="DELETE" /> 
                </allowMethods>
            </add>
            <add origin="http://localhost:1502">
                <allowMethods>
                    <add method="GET" />
                    <add method="HEAD" />
                    <add method="POST" />
                    <add method="PUT" /> 
                    <add method="DELETE" /> 
                </allowMethods>
            </add>
        </cors>
    </system.webServer>
</configuration>

ここで構成のリファレンスを見つけることができます:https : //docs.microsoft.com/en-us/iis/extensions/cors-module/cors-module-configuration-reference


それが言うようにこれが機能する場合は、3年前にこれを投稿したいと思います!うわあ!
マイケル


1

このコードをasp.net webapiプロジェクトに追加できます

Global.asaxファイル内

    protected void Application_BeginRequest()
{
    string origin = Request.Headers.Get("Origin");
    if (Request.HttpMethod == "OPTIONS")
    {
        Response.AddHeader("Access-Control-Allow-Origin", origin);
        Response.AddHeader("Access-Control-Allow-Headers", "*");
        Response.AddHeader("Access-Control-Allow-Methods", "GET,POST,PUT,OPTIONS,DELETE");
        Response.StatusCode = 200;
        Response.End();
    }
    else
    {
        Response.AddHeader("Access-Control-Allow-Origin", origin);
        Response.AddHeader("Access-Control-Allow-Headers", "*");
        Response.AddHeader("Access-Control-Allow-Methods", "GET,POST,PUT,OPTIONS,DELETE");
    }
}

0

owinミドルウェアを使用して、複数のcorの起点を定義できるcorsポリシーを定義できます。

return new CorsOptions
        {
            PolicyProvider = new CorsPolicyProvider
            {
                PolicyResolver = context =>
                {
                    var policy = new CorsPolicy()
                    {
                        AllowAnyOrigin = false,
                        AllowAnyMethod = true,
                        AllowAnyHeader = true,
                        SupportsCredentials = true
                    };
                    policy.Origins.Add("http://foo.com");
                    policy.Origins.Add("http://bar.com");
                    return Task.FromResult(policy);
                }
            }
        };

-3

あなただけが必要です:

  • Global.asaxをプロジェクトに追加し、
  • <add name="Access-Control-Allow-Origin" value="*" />web.configから削除 します。
  • その後、Application_BeginRequestGlobal.asax のメソッドにこれを追加します。

    HttpContext.Current.Response.AddHeader("Access-Control-Allow-Origin","*");
    
    if (HttpContext.Current.Request.HttpMethod == "OPTIONS")
    {
        HttpContext.Current.Response.AddHeader("Access-Control-Allow-Methods", "POST,GET,OPTIONS,PUT,DELETE");
        HttpContext.Current.Response.AddHeader("Access-Control-Allow-Headers", "Content-Type, Authorization, Accept");
        HttpContext.Current.Response.End();
    }

これがお役に立てば幸いです。それは私のために働きます。


「...- Origin:*」の追加は、資格情報を許可する場合を除いて機能します。allow-credentialsをtrueに設定している場合は、ドメインを指定する必要があります(単に*ではありません)。この問題の核心はここにあります。それ以外の場合は、「... allow-credentials:false」を指定して、それで完了できます。
Richard
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.