启用CORS的Web API无法添加标头

7

我正在使用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);
    }
}

我需要在WebApiConfig.cs中注册cors。

 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:成功了!...我启用了跟踪并找到了错误。
 The collection of headers 'accept,content-type' is not allowed

所以我刚刚编辑了GetPolicyForControllerAndOrigin方法来允许它们。现在一切都正常了,但我很困惑,因为在我的另一个项目中(我从中复制了DynamicPolicyProviderFactory),我不需要这样做。


1
令人惊讶的是,他们在CORS设置上制造了如此复杂的多种不同方式,每种方式都“几乎可以”工作,而文档则非常糟糕,到处都是,并且没有解释你应该实现哪一半的东西才能使其正常工作。 - tkit
1
@Si8 DynamicPolicyProviderFactory 就像其他类一样,可以组织在任何代码文件夹下。对于 MyApp.Properties.Settings,它在 web.config 中,但如果您想要一个用于编辑该特定部分的 UI,则可以在 VS 中右键单击项目 > 属性 > 设置。 - Mike_G
谢谢,那很有帮助。所以我不需要在每个API文件上面添加[EnableCors()]吗? - Si8
不,您不需要将[EnableCors()]添加到操作或控件中。如果您手动编辑web.config中的应用程序设置,它会在UI编辑器中出现问题。我通常使用UI编辑器创建web.config中的部分(因此不必编写所有设置的xml),然后手动进行编辑。 - Mike_G
1
不,只需使用<string>http*://mysite.com</string>(将命中http和https)或类似<string>http*://*.mysite.com</string>以包括子域。 - Mike_G
显示剩余4条评论
1个回答

5

在应用程序中启用跟踪。您应该会看到一个错误。

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

只需将它们添加到策略的允许标头中,一切都应该正常工作。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接