【问题标题】:IIS and jQuery CORS - 401 returned on preflightIIS 和 jQuery CORS - 预检时返回 401
【发布时间】:2018-03-15 01:35:21
【问题描述】:

概述:

我可以访问服务器 (IIS) 和代码(jQuery、MVC 项目等)。我们需要设置 CORS,以便前端开发人员能够访问我们 QA 服务器上的 API。 IIS 服务器启用了“基本身份验证”,并启用了以下“Access-Control-Allow-XX”:

  • Credentials : true
  • Headers : Content-Type, Authorization
  • Methods : GET,POST,OPTIONS,HEAD
  • Origin : http://myLocal
    // I did have*as this, but the response was complaining that I could not have a wildcard -- did not understand this

jQuery(省略 U/P)

    $.ajax({
        dataType: "json",
        type: "POST",
        url: 'https://ourQAserver.com' + fcs_vars.subscribeURL,
        headers: {
            "Authorization": "Basic " + btoa('USERNAME:PASS')
            //,'Access-Control-Allow-Origin' : '*'
        },
        xhrFields: {
            withCredentials: true
        },
        //beforesend: function (xhr) {
        //    xhr.setrequestheader('Authorization', 'Basic ' + btoa('USERNAME:PASS'));
        //},
        //crossdomain: true,
        contentType: "application/json",
        data: user,
        cache: false,
        ....
        ....

正如您在上面看到的,我尝试了不同的方法来让它发挥作用。我从请求中收到的当前错误是:

加载失败 https://ourQAserver.com/area/controller/action: 预检响应包含无效的 HTTP 状态代码 401

服务器没有“响应”(在 Chrome 开发工具中)

一个想法是我必须在 MVC 中启用 CORS,使用 Nuget pkg,然后将属性添加到控制器上,但我没有这样做,因为我可以访问 IIS 本身。

【问题讨论】:

  • 我认为可能不是 CORS,而是身份验证。您可以尝试访问没有[Authorize] 属性的控制器吗?
  • 在我添加 Authorization 标头属性之前(这不是 MVC 属性,而是用于发送编码的 base64 字符串作为用户名/密码),我在 Google 的控制台中收到了一个不同的错误,与事实上,我(当时)没有发送信用。不幸的是,我无法从 IIS 应用程序池中删除“基本身份验证”,因为不应从网络外部访问我们的 QA 环境。
  • 您需要将服务器后端配置为不需要对OPTIONShttps://ourqaserver.com/area/controller/action 的请求进行授权。问题中引用的消息中的 401 状态代码表示服务器需要对 OPTIONS 请求进行授权,但授权失败,因为请求不包含所需的凭据。原因是,OPTIONS 请求是作为 CORS 的一部分由您的浏览器自动发送的,并且浏览器不会将 Authorization 标头添加到该预检 OPTIONS 请求中。
  • 更详细: 1. 您的代码告诉您的浏览器它想要发送带有授权标头的请求。 2. 浏览器说,好的,带有 Authorization 标头的请求要求我执行 CORS 预检 OPTIONS 以确保服务器允许带有 Authorization 标头的请求。 3. 浏览器将选项发送到服务器不带Authorization 标头。 4. 服务器看到 OPTIONS 但由于缺少标头而以 401 拒绝它。 5. 浏览器期望预检得到 200 响应,但得到 401。所以浏览器停在那里,从不尝试来自您的代码的 POST 请求。
  • 因此,您必须弄清楚当前服务器端代码的哪一部分导致您的服务器需要对 OPTIONS 进行授权,并对其进行更改,以便它在不需要授权的情况下处理 OPTIONS。 developer.mozilla.org/en-US/docs/Web/HTTP/… 一般解释了为什么浏览器会发出 CORS 预检 OPTIONS 请求,以及响应必须包含哪些标头;具体来说,在这种情况下,对预检 OPTIONS 的响应必须具有“Access-Control-Allow-Methods: POST”和“Access-Control-Allow-Headers: Authorization”响应头。

标签: jquery asp.net-mvc iis cors


【解决方案1】:

尝试添加一个 OPTIONS 端点。 客户端将首先发出 OPTIONS 请求,如果成功,则发出 GET 或 POST 调用。

    /// <summary>
    /// OPTIONS method that is used by client browser to make a handshake
    /// </summary>
    /// <returns>bool object</returns>
    [HttpOptions]
    public bool Options()
    {
        return true;
    }

【讨论】:

    【解决方案2】:

    非常感谢@sideshowbarker 的帮助,为我指明了正确的道路

    在 IIS 中添加了这些 (4) customHeaders。显然,当 IIS 服务器需要凭据时,您必须指定一个值(而不是使用通配符 *)Access-Control-Allow-Origin。此外,Headers 没有通配符,因此需要大量。

    我们需要列出多个Origins,并且由于Access-Control-Allow-Origin 非常严格(因为只能有一个完全声明的URL),我发现这个漂亮的重写来解决这个问题。

    Access-control-allow-origin with multiple domains

    这是所有可能的标题的列表

    Cors Access-Control-Allow-Headers wildcard being ignored?

    这是关于通过 IIS 重写重定向 OPTIONS 请求的帖子

    CORS preflight request returning HTTP 401 with windows authentication

    <rewrite>
      <rules>
        <clear />
        <rule name="CORS Preflight Anonymous Authentication" stopProcessing="true">
          <match url=".*" />
          <conditions>
            <add input="{REQUEST_METHOD}" pattern="^OPTIONS$" />
          </conditions>
          <action type="CustomResponse" statusCode="200" statusReason="Preflight" statusDescription="Preflight" />
        </rule>
      </rules>
      <outboundRules>
        <!-- Added for CORS -->
        <rule name="AddCrossDomainHeader">
          <match serverVariable="RESPONSE_Access-Control-Allow-Origin" pattern=".*" />
          <conditions>
            <add input="{HTTP_ORIGIN}" pattern="(http(s)?://((.+\.)?domain1\.com|(.+\.)?domain2\.com|(.+\.)?domain3\.com))" />
          </conditions>
          <action type="Rewrite" value="{C:0}" />
        </rule>
      </outboundRules>
    </rewrite>
    


    你不需要在这里指定Access-Control-Allow-Origin b/c 我们在重写中使用它

        <add name="Access-Control-Allow-Headers" value="X-Requested-With, Accept, Accept-Charset, Accept-Encoding, Accept-Language, Accept-Params, Access-Control-Allow-Credentials, Access-Control-Allow-Headers, Access-Control-Allow-Methods, Access-Control-Allow-Origin, Access-Control-Request-Headers, Access-Control-Request-Method, Allow, Authorization,Content-Length, Content-Location, Content-Range, Content-Script-Type, Content-Security-Policy, Content-Style-Type, Content-Transfer-Encoding, Content-Type, Cookie, GET, HEAD, Keep-Alive, OPTIONS, Origin, POST, Pragma, Referer, Refresh, Status, User-Agent " />
        <add name="Access-Control-Allow-Methods" value="GET,POST,OPTIONS" />
        <add name="Access-Control-Allow-Credentials" value="true" />
    

        $.ajax({
            dataType: "json",
            type: "POST",
            url: 'https://qa.URL.com' + fcs_vars.subscribeURL,
            headers: {
                "Authorization": "Basic " + btoa('myUser:myPass')
            },
            xhrFields: {
                withCredentials: true
            },
            crossdomain: true,
            contentType: "application/json",
            data: user,
            complete: function (response) {
                if (response.readyState == 4) { 
                    // code here
    

    【讨论】:

      猜你喜欢
      • 2013-01-31
      • 2013-08-06
      • 2019-10-21
      • 1970-01-01
      • 2016-11-07
      • 2013-10-24
      • 1970-01-01
      • 1970-01-01
      • 2021-03-14
      相关资源
      最近更新 更多