ASP.NET WebApi - 为多个Origins启用CORS

时间:2016-10-13 18:13:46

标签: .net angularjs asp.net-web-api cors

我一直在尝试为我的API启用多个来源的CORS而没有任何成功。

这就是我所做的。

创建了CORS政策

 [AttributeUsage(AttributeTargets.All, AllowMultiple =false, Inherited =true)]
    public class TCCorsPolicyProvider : Attribute, ICorsPolicyProvider
    {
        private CorsPolicy _policy;

        public TCCorsPolicyProvider()
        {
            _policy = new CorsPolicy
            {
                SupportsCredentials = true
            };
            string[] allowedOrigins = "john.doe,ava.wise".Split(',');
            string[] allowedMethods = "GET,POST,PUT,OPTIONS".Split(',');
            string[] allowedHeaders = "Content-Type,Origin,Authorization,Accept".Split(',');
            // Add allowed origins.
            foreach (string origin in allowedOrigins)
                _policy.Origins.Add(origin);
            foreach (string method in allowedMethods)
                _policy.Methods.Add(method);
            foreach (string header in allowedHeaders)
                _policy.Headers.Add(header);
        }

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

创建工厂

public class TCCorsPolicyProviderFactory : ICorsPolicyProviderFactory
    {
        ICorsPolicyProvider _provider;
        public TCCorsPolicyProviderFactory()
        {
            _provider = new TCCorsPolicyProvider();
        }
        public ICorsPolicyProvider GetCorsPolicyProvider(HttpRequestMessage request)
        {
            return _provider;
        }
    }

在WebApiConfig.cs类中启用了Cors

config.SetCorsPolicyProviderFactory(new TCCorsPolicyProviderFactory());
            config.EnableCors();

确保在Global.asax Application_Start中进行适当的注册

 GlobalConfiguration.Configure(WebApiConfig.Register);

当上述操作不起作用时,我甚至手动将策略属性应用于我的基本控制器,所有其他控制器都从该控制器继承

[TCCorsPolicyProvider]
    public class BaseApiController : ApiController
    {
        public string IpAddress
        {
            get { return ContextHelper.GetIpAddress(); }
        }

        private bool _disposed;
        protected virtual void Dispose(bool disposing, Action disposeAction)
        {
            if (!_disposed)
            {
                if (disposing)
                {
                    disposeAction();
                }
            }
            _disposed = true;
        }
    }

但是我收到以下错误(从Angular调用Api)

  

XMLHttpRequest无法加载hqidwtcdwa01 / api / localizations / reloadCache。   请求中不存在“Access-Control-Allow-Origin”标头   资源。因此,'ava.wise'原因不允许访问。该   响应有HTTP状态码401。

hqidwtcdwa01是目的地,ava.wise是原点。

到目前为止,我发现xmlhttp响应中的http响应头不包含Access-Control-Allow-Origin。但是当我使用HttpCient时,我可以看到标题。 HttpClient Response

Postman Response

3 个答案:

答案 0 :(得分:0)

我和owincontext建立mvc api的问题非常类似,我不得不添加

#if DEBUG //Notice this is only when I'm in debug mode.
 context.OwinContext.Response.Headers.Add("Access-Control-Allow-Origin", new[] { "*" });
#endif

但是当我部署了特定于所需来源的添加标头时。 由于您的错误类似,因此可能有助于添加Access-Control-Allow-Origin : ava.wise标头并检查它是否已解决。希望它有助于缩小您的问题范围。

您希望在标题中包含的内容示例,请注意,选项方法会将已接受的来源提取到任何&#34; *&#34;。

enter image description here

--- --- UPDATE

请尝试更新web.config添加标题。 Custom Headers 这应反映在答复中。显然这在代码中是可能的,但开始很简单。

 <configuration>   <system.webServer>
  <httpProtocol>
     <customHeaders>
        <remove name="Access-Control-Allow-Origin" />
        <add name="Access-Control-Allow-Origin" value="*" />
     </customHeaders>
  </httpProtocol>   
 </system.webServer>
</configuration>

答案 1 :(得分:0)

我相信cors理论上允许多个起源但实际上不允许。对于我的网站,我创建了一个新的CORS属性,并根据传入返回一个允许的来源,这比使用*

更安全
 [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method,
            AllowMultiple = false)]
public class GlobalEnableCorsAttribute :


 Attribute, ICorsPolicyProvider
    {
        public Boolean SupportsCredentials = true;
        public CorsHandler handle = new CorsHandler();
        public async Task<CorsPolicy> GetCorsPolicyAsync(
          HttpRequestMessage request, CancellationToken cancellationToken)
        {
             var corsRequestContext = request.GetCorsRequestContext();
            var originRequested = corsRequestContext.Origin;


            string approvedOrigin = handle.approveCorsOrigin(originRequested);

            if(!string.IsNullOrEmpty(approvedOrigin))
            {
                // Grant CORS request
                var policy = new CorsPolicy
                {
                    AllowAnyHeader = true,
                    AllowAnyMethod = true,
                    SupportsCredentials = true
                };

                // add headers
                policy.Headers.Add("content-type");
                policy.Headers.Add("withcredentials");
                policy.Headers.Add("Access-Control-Allow-Headers");
                policy.Headers.Add("Access-Control-Allow-Origin");
                policy.Headers.Add("Origin");
                policy.Headers.Add("Accept");
                policy.Headers.Add("X-Requested-With");
                policy.Headers.Add("Access-Control-Request-Method");
                policy.Headers.Add("Access - Control - Request - Headers");


                policy.Origins.Add(approvedOrigin);
                return policy;
            }
            else
            {
                // Reject CORS request
                return null;
            }
        }



    }

原始搜索从服务器配置值

获取允许的来源
 public class CorsHandler
{
    public string approveCorsOrigin(string providedOrigin)
    {
        // load list of web.config origins
        string fullList = Properties.Settings.Default.CORSOriginPermittedSite;

        if (!string.IsNullOrEmpty(fullList))
        {
            string[] originArray = fullList.Split(new char[]{ ','}, StringSplitOptions.RemoveEmptyEntries);

            foreach(string approvedOrigin in originArray)
            {
                if (providedOrigin.Trim() == approvedOrigin.Trim())
                {
                    return providedOrigin;
                }
            }
        }
        return null;
    }
}

用法如下

 public static void Register(HttpConfiguration config)
    {
        if (Properties.Settings.Default.CORSOriginPermittedSite != null && !string.IsNullOrWhiteSpace(Properties.Settings.Default.CORSOriginPermittedSite))
        {
            var cors = new GlobalEnableCorsAttribute();
            config.EnableCors(cors);
        }
    }

最后这个代码是针对webapi设置的,但是应该具有可比性,你也(如果使用类似的话)需要让飞行前应对相同的原始搜索..

答案 2 :(得分:0)

我是用肮脏的方式做到的,也许不是那个建议但是这让我走了(假设你安装了cors nuget,web api 2.0和.NET 4.5):

的web.config:

<appSettings>
    <add key="AllowedDomains" value="http://domain0:8009, http://domain1:8009"/>
 </appSettings>

Configs.cs:

public static string AllowedDomains {
        get {
            return @ConfigurationManager.AppSettings["AllowedDomains"].ToString();
        }
    }

WebApiConfig:

    public static void Register(HttpConfiguration config)
    {
        var attribute = new System.Web.Http.Cors.EnableCorsAttribute(Configs.AllowedDomains, "*", "*"); //domains, headers, methods - you could do the same for the other args.
        config.EnableCors(attribute); //global
    }

要按Controller / action进行过滤,只需在顶部添加属性:

[System.Web.Http.Cors.EnableCors(origins: "http://domain2:8009", headers: "*", methods: "*")]

让我知道任何进展或评论。希望这可以帮助。谢谢! :)