【问题标题】:CORS enabled Web API fails to add header启用 CORS 的 Web API 无法添加标头
【发布时间】:2014-11-17 18:05:30
【问题描述】:

我正在使用DynamicPolicyProviderFactory,如here 所述。下面是我的 DynamicPolicyProviderFactory 版本:

public class DynamicPolicyProviderFactory : ICorsPolicyProviderFactory
{
    private readonly HashSet<Regex> _allowed;

    public DynamicPolicyProviderFactory(IEnumerable allowedOrigins)
    {
        _allowed = new HashSet<Regex>();

        foreach (string pattern in allowedOrigins.Cast<string>()
            .Select(Regex.Escape)
            .Select(pattern => pattern.Replace("*", "w*")))
        {
            _allowed.Add(new Regex(pattern, RegexOptions.IgnoreCase));
        }

        if (_allowed.Count >= 1)
            return;

        //if nothing is specified, we assume everything is.
        _allowed.Add(new Regex(@"https://\w*", RegexOptions.IgnoreCase));
        _allowed.Add(new Regex(@"http://\w*", RegexOptions.IgnoreCase));
    }

    public ICorsPolicyProvider GetCorsPolicyProvider(HttpRequestMessage request)
    {
        var route = request.GetRouteData();
        var controller = (string)route.Values["controller"];
        var corsRequestContext = request.GetCorsRequestContext();
        var originRequested = corsRequestContext.Origin;
        var policy = GetPolicyForControllerAndOrigin(controller, originRequested);
        return new CustomPolicyProvider(policy);
    }

    private CorsPolicy GetPolicyForControllerAndOrigin(string controller, string originRequested)
    {
        // Do lookup to determine if the controller is allowed for
        // the origin and create CorsPolicy if it is (otherwise return null)

        if (_allowed.All(a => !a.Match(originRequested).Success))
            return null;

        var policy = new CorsPolicy();
        policy.Origins.Add(originRequested);
        policy.Methods.Add("GET");
        policy.Methods.Add("POST");
        policy.Methods.Add("PUT");
        policy.Methods.Add("DELETE");
        return policy;
    }
}

public class CustomPolicyProvider : ICorsPolicyProvider
{
    private readonly CorsPolicy _policy;

    public CustomPolicyProvider(CorsPolicy policy)
    {
        this._policy = policy;
    }

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

我注册 cors 的调用赢得了 WebApiConfig.cs

 config.EnableCors();
 config.SetCorsPolicyProviderFactory(new DynamicPolicyProviderFactory(Settings.Default.AllowedDomains));

我的应用程序设置正在通过:

<MyApp.Properties.Settings>
  <setting name="AllowedDomains" serializeAs="Xml">
    <value>
      <ArrayOfString xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
        <string>http://localhost</string>
        <string>http*://*.domain1.com</string>
        <string>http*://*.domain2.com</string>
      </ArrayOfString>
    </value>
  </setting>
</MyApp.Properties.Settings>

尽管有这些设置,但如果我从http://mg.domain1.comhttp://localhost 发出请求,我的回复中不会出现Access-Control-Allow-Origin 标头。我正在使用 Web Api 2.2 和 Microsoft.AspNet.Cors 5.2.2。

编辑:我发现如果我在控制器上使用EnableCors 属性,或者全局启用它(config.EnableCors(new EnableCorsAttribute("*", "*", "*"));)它可以工作,所以它一定与我的动态工厂有关。令人沮丧的是,DynamicPolicyProvider 是从我正在使用的另一个项目中复制/粘贴的,效果很好。

编辑2:成功!...我启用tracing并发现错误

 The collection of headers 'accept,content-type' is not allowed

所以我只是编辑了GetPolicyForControllerAndOrigin 方法以允许它们。现在一切正常,除了我很困惑,因为我不必在我的另一个项目(我从中复制 DynamicPolicyProviderFactory 的那个项目)中跳过这一圈。

【问题讨论】:

  • 令人惊讶的是,他们使用多种不同的方式设置 CORS 设置有多复杂,您可以在每个“几乎可以工作”的地方进行设置,而且文档很糟糕,到处都是,没有解释你应该实现一半的东西才能让它工作。
  • @pootzko 我绝对同意!还有 Mike_G,我可以将 DynamicPolicyProviderFactory.cs 放在根文件夹中还是必须放在某个文件夹中?这是什么:&lt;/MyApp.Properties.Settings&gt;,我在 Web.config 的任何地方都找不到它。那是appSettings吗?
  • @Si8 DynamicPolicyProviderFactory 就像任何其他类一样,可以组织在任何代码文件夹下。对于MyApp.Poperties.Settings,它位于 web.config 中,但如果您想要一个用于编辑该特定部分的 UI,请在 VS > Properties > Settings 中右键单击您的项目
  • 这有帮助,谢谢。这样我就不用在每个 API 文件上面加上 [EnableCors()] 了吗?
  • 不,只需使用 &lt;string&gt;http*://mysite.com&lt;/string&gt;(将访问 http 和 https)或类似 &lt;string&gt;http*://*.mysite.com&lt;/string&gt; 的东西来包含子域。

标签: c# asp.net asp.net-web-api asp.net-web-api2


【解决方案1】:

在应用中启用tracing。你应该会看到一个错误

The collection of headers 'accept,content-type' is not allowed

只需将这些添加到策略的允许标题中,一切都会正常。

【讨论】:

    猜你喜欢
    • 2017-12-16
    • 2017-07-01
    • 2017-07-09
    • 2021-08-04
    • 2019-02-11
    • 2019-12-20
    • 2020-01-09
    • 2017-05-23
    • 1970-01-01
    相关资源
    最近更新 更多