Access-Control-Allow-Origin - 访问MVC web api 2的多个域

时间:2017-05-04 06:40:10

标签: cors asp.net-web-api2

我需要从我的Web API允许来自多个域的CORS请求。但是,我不想通过在web配置中执行以下操作让所有人都能打开它。

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

我只需要允许域名白名单能够向我的API发出CORS请求。

我见过this SO question但是,我最好不要使用.htaccess文件,因为我无法控制IIS服务器。

我尝试了this SO answerthis blog

问题是,它总是返回以下错误。

  

请求的资源上没有'Access-Control-Allow-Origin'标头。

这是我的实施。

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true, Inherited = true)]
public class EnableCORSAttribute : ActionFilterAttribute
{
    private string[] origins;
    private string[] methods;

    public EnableCORSAttribute(string[] origins = null, string[] methods = null)
    {
        this.origins = origins;
        this.methods = methods;
    }

    public override void OnActionExecuted(ActionExecutedContext actionExecutedContext)
    {
        if (origins == null || !origins.Any())
        {
            //Allow all  
            HttpContext.Current.Response.AppendHeader("Access-Control-Allow-Origin", "*");
        }
        else if (origins.Contains(HttpContext.Current.Request.Url.Host, StringComparer.InvariantCultureIgnoreCase))
        {
            //Allow only if matching  
            HttpContext.Current.Response.AppendHeader("Access-Control-Allow-Origin", HttpContext.Current.Request.Url.Host);
        }

        if (methods == null || !methods.Any())
        {
            //Allow all  
            HttpContext.Current.Response.AppendHeader("Access-Control-Allow-Methods", "*");
        }
        else if (methods.Contains(HttpContext.Current.Request.HttpMethod, StringComparer.InvariantCultureIgnoreCase))
        {
            //Allow only specified  
            HttpContext.Current.Response.AppendHeader("Access-Control-Allow-Methods", HttpContext.Current.Request.HttpMethod);
        }
    }
}    

这是我使用属性装饰BaseController的方式。

[EnableCORS(origins: new string[] { "localhost" }, methods: new string[] { "GET", "POST", "OPTIONS" })]
public class BaseController : ApiController
{
    // GET api/<controller>
    public HttpResponseMessage Options()
    {
        return new HttpResponseMessage { StatusCode = HttpStatusCode.OK };
    }
}

我还尝试从Global.asax文件注册此属性。

GlobalFilters.Filters.Add(new EnableCorsAttribute());
RegisterGlobalFilters(GlobalFilters.Filters);

但仍然得到同样的错误。不确定我还缺少什么。

我还尝试了Microsoft.AspNet.WebApi.Cors Nuget Package并将其放入WebApiConfig文件中。

var enableCorsAttribute = new EnableCorsAttribute("http://localhost:59427",
                                   "Origin, Content-Type, Accept, Authorization",
                                   "GET, POST, OPTIONS");    
config.EnableCors(enableCorsAttribute);

它适用于一个域,但只要我添加另一个域,它也会开始抛出相同的错误。

1 个答案:

答案 0 :(得分:0)

事实证明这比想象和想象的要简单。

我需要做的就是查看请求和响应标头。

我尝试添加以允许CORS请求的其他域名是发送一些自定义标头。

所以我允许那些特定的自定义标题并且它有效。

这是最终的解决方案。

我的BaseController

// No fancy decoration here... :)
public class BaseController : ApiController
{
    // GET api/<controller>
    public HttpResponseMessage Options()
    {
        return new HttpResponseMessage { StatusCode = HttpStatusCode.OK };
    }
}

我的WebApiConfig

public static class WebApiConfig
{
    public static void Register(HttpConfiguration config)
    {
        //Some API routes here...

        var enableCorsAttribute = new EnableCorsAttribute(
            // Comma separated whitelist of allowed domains, notice no slash ('/') at the end of domain
            "http://local.ui.two:9003,http://local.ui.one:9001", 
            // Allowed Custom Headers
            "Origin, X-Requested-With, Content-Type, Accept, Authorization, Cache-Control, If-Modified-Since, Pragma",
            // Allowed methods
            "GET, PUT, POST, DELETE, OPTIONS"
        );

        config.EnableCors(enableCorsAttribute);
    }
}

并在Global.asax注册了此WebApiConfig。

protected void Application_Start()
{
    GlobalConfiguration.Configure(WebApiConfig.Register);
}
  • web.config
  • 中无需任何操作
  • 不需要编写自定义花哨属性,为什么重新发明轮子!? :)
  • 仅使用Nuget Package Microsoft.AspNet.WebApi.Cors

This other question我问过两个站起来帮助社区的天才,给了我正确的方向。