【问题标题】:Safari fails CORSSafari 未能通过 CORS
【发布时间】:2014-12-11 23:40:12
【问题描述】:

我正在使用DynamicPolicyProviderFactory 来确定在 Asp.Net Web API 2.2 应用程序中是否允许来自域的请求。为了做出这个决定,我使用了 Web.Config 中定义的几个 RegEx 模式

 <applicationSettings>
<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>
</applicationSettings>

然后在我的DynamicPolicyProviderFactory 中创建一个我可以使用的正则表达式:

 //constructor
 public DynamicPolicyProviderFactory(IEnumerable allowedOrigins)//allowedDrigins is the strings passed from the config        {
        _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 > 0)
            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);
    }

    //this is where the magic happens
    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.Headers.Add("accept");
        policy.Headers.Add("content-type");

        policy.Origins.Add(originRequested);
        policy.Methods.Add("GET");
        policy.Methods.Add("POST");
        policy.Methods.Add("PUT");
        policy.Methods.Add("DELETE");
        policy.Methods.Add("OPTIONS");

        return policy;
    }

假设请求来源是:http://sub.domain1.com,脚本位置是http://sub.domain1.com:8080。这在 Chrome、IE、FireFox 和 Opera 中完美运行,但在 Safari 中失败。奇怪的是 Safari 在浏览器控制台中给出的错误是

Failed to load resource: Origin http://sub.domain1.com is not allowed by Access-Control-Allow-Origin

会发生什么?

我观察到的另一个奇怪之处是,如果我的来源和脚本位置都是 http:sub.domain1.com:8080 CORS 请求由 Safari 发出(并通过),但其他浏览器正确地将其视为同一来源。

编辑:我发现如果我在 GetPolicyForControllerAndOrigin 返回 null 的位置设置断点,它永远不会被命中,并且会正确创建和返回策略。

编辑 2: 我检查了服务器对 Safari 的 OPTIONS 请求的响应,发现响应中缺少标头 Access-Control-Allow-HeadersAccess-Control-Allow-Origin 标头。此外,在请求方面,Safari 没有添加 Host 标头。这是必需的吗?这就是它失败的原因吗?

【问题讨论】:

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


    【解决方案1】:

    问题在于 Safari 的 OPTIONS 请求。我只允许acceptcontent-type 允许标题,但Safari 也要求origin

    【讨论】:

      猜你喜欢
      • 2021-07-18
      • 1970-01-01
      • 2019-01-15
      • 1970-01-01
      • 2016-08-17
      • 2013-04-10
      • 2020-12-22
      • 2019-07-24
      • 2011-12-01
      相关资源
      最近更新 更多