【问题标题】:Internet Explorer 11 replaces Authorization headerInternet Explorer 11 替换授权标头
【发布时间】:2015-04-21 08:34:03
【问题描述】:

什么会导致 Internet Explorer 替换 HTTP 标头

Authorization : Bearer <server-provided-token>

Authorization : Negotiate <some token>

何时发出 AJAX 请求?

详情

在 Internet Explorer 中,一些配置为包含标头 Authorization: Bearer ... 的 AJAX 请求由 Internet Explorer 发送,而标头为 Authorization: Negotiate ...

例如,Fiddler 显示三个请求中的前两个包含Authorization : Bearer... 标头,而第三个突然包含Authorization : Negotiate... 标头。前两个请求成功,第三个请求失败,因为请求无法正确验证。

所有请求都是使用相同的客户端代码构造的,并且一个接一个地发出(在一秒钟内)。我已经验证Authorization 标头在所有三种情况下都正确包含Bearer 令牌,直到将请求提供给浏览器为止。

另外,我在 Chrome 中没有看到相同的行为;它只发生在 IE 中。

请求 1

GET http://localhost/myapp/api/User HTTP/1.1 接受:应用程序/json、文本/纯文本、*/* 授权:承载oEXS5IBu9huepzW6jfh-POMA18AUA8yWZsPfBPZuFf_JJxq-DKIt0JDyPXSiGpmV_cpT8FlL3D1DN-Tv5ZbT73MTuBOd5y75-bsx9fZvOeJgg04JcO0cUajdCH2h5QlMP8TNwgTpHg-TR9FxyPk3Kw6bQ6tQCOkOwIG_FmEJpP89yrOsoYJoCfrAoZ7M4PVcik9F9qtPgXmWwXB2eHDtkls44wITF_yM_rPm5C47OPCvMVTPz30KwoEPi6fHUcL3qHauP-v9uypv2e48TyPHUwLYmNFxyafMhBx4TkovnRcsdLHZiHmSjMq0V9a2Vw70 参考:http://localhost/client/login.html 接受语言:en-US 接受编码:gzip,放气 用户代理:Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) 像 Gecko 主机:本地主机 DNT: 1 连接:保持活动

请求 2

POST http://localhost/myapp/api/Permissions HTTP/1.1 引用者:http://localhost/client/#/Dashboard 内容类型:应用程序/json 授权:承载oEXS5IBu9huepzW6jfh-POMA18AUA8yWZsPfBPZuFf_JJxq-DKIt0JDyPXSiGpmV_cpT8FlL3D1DN-Tv5ZbT73MTuBOd5y75-bsx9fZvOeJgg04JcO0cUajdCH2h5QlMP8TNwgTpHg-TR9FxyPk3Kw6bQ6tQCOkOwIG_FmEJpP89yrOsoYJoCfrAoZ7M4PVcik9F9qtPgXmWwXB2eHDtkls44wITF_yM_rPm5C47OPCvMVTPz30KwoEPi6fHUcL3qHauP-v9uypv2e48TyPHUwLYmNFxyafMhBx4TkovnRcsdLHZiHmSjMq0V9a2Vw70 接受:应用程序/json、文本/纯文本、*/* 接受语言:en-US 接受编码:gzip,放气 用户代理:Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) 像 Gecko 主机:本地主机 内容长度:1419 DNT: 1 连接:保持活动 Pragma:无缓存

请求 3

GET http://localhost/myapp/api/UserPreferences/Dashboard HTTP/1.1 引用者:http://localhost/client/#/Dashboard 内容类型:应用程序/json 授权:协商 YHsGBisGAQUFAqBxMG+gMDAuBgorBgEEAYI3AgIKBgkqhkiC9xIBAgIGCSqGSIb3EgECAgYKKwYBBAGCNwICHqI7BDlOVExNU1NQAAEAAACXsgjiBgAGADMAAAALAAsAKAAAAAYBsR0AAAAPVk1ERVZFTlYtU1JTQ0VSSVM= 接受:应用程序/json、文本/纯文本、*/* 接受语言:en-US 接受编码:gzip,放气 用户代理:Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) 像 Gecko 连接:保持活动 DNT: 1 主机:本地主机

请求是通过 AngularJS $http 服务发出的,后端是托管在 IIS 中的 ASP.NET Web API。

【问题讨论】:

  • 嗨 shrichards - 你有没有想过这个问题?我似乎在使用 IE 11 时遇到了同样的问题。
  • @JoshuaBarron 我一直无法确定问题的根本原因。我通过创建一个单独的服务来解决这个问题,该服务具有发行令牌的单一职责。在 IIS 中,该令牌服务被配置为支持 Windows 和匿名身份验证。然后将使用令牌进行身份验证的服务配置为仅在 IIS 中使用匿名身份验证(因为身份验证是通过中间件中的令牌处理的)。这使 IE 在访问安全服务时无法尝试与 IIS 执行集成身份验证。
  • 您能否提供一个更详细的示例,您是如何制作此服务的(在 github 或 pastebin 中)。我因这个问题失去了两个多星期,但仍然找不到解决方法。提前致谢。
  • Martin - 我已经有了 shrichards 描述的相同设置。我跟着bitoftech.net/2014/09/24/… 进行了设置。对于客户提出的一些请求,我仍然遇到此问题(请参阅我的链接问题)。
  • 我也看到了这个,我正在寻找一个好的解决方案。关注这个帖子,如果我找到解决方案会发布

标签: angularjs internet-explorer asp.net-web-api owin


【解决方案1】:

我在一个 knockoutjs 应用程序中遇到了同样的问题,它在 Chrome 和 Firefox 中运行良好,但在 IE 中却不行。

我还使用了 Fiddler,并注意到第一个 ajax 调用按预期使用 Bearer 并成功返回。但随后 IE 开始循环并使用 Negotiate 授权一遍又一遍地发送后续的 ajax 调用!

在我的情况下,这是 IE 中的某种时间问题,我通过使在渲染期间加载数据的 ajax 调用同步来解决它。

    me.loadLimits = function () {
      $.ajax({
        type: 'GET',
        dataType: 'json',
        contentType: 'application/json',
        url: '/api/workrate/limits',
        headers: me.headers,
        async: false,
        success: function (result) {
    ...

【讨论】:

    【解决方案2】:

    我们遇到了 Internet Explorer 缓存凭据的问题。我们可以使用以下脚本来解决这个问题:

    document.execCommand('ClearAuthenticationCache', 'false');
    

    见:Wikipedia

    【讨论】:

    • 非常感谢。完美的解决方案。只需在 index.html 中 html 标签 之后添加这一行
    • 这不起作用..至少对我们来说。它触发了对每个请求的重新提示身份验证,我们仍然看到 Authorization: Basic 标头覆盖了我们的 Authorization: Bearer 标头:(
    • 这在我们的案例中有效。 API:.Net Core 2.1;前端:角度;基于令牌的身份验证。在身份验证之后和任何其他 API 调用之前添加了 ClearAuthenticationCache。
    【解决方案3】:

    我也遇到过这个问题。

    奇怪的是它在我的开发机器上运行良好,但在我部署它时出现了问题。 它再次在 Chrome、Firefox 等中运行良好。

    事实证明,问题在于 IE 检测到该站点位于 localintranet 区域,因此试图自动尝试登录(它由组策略设置 - 这是一个内部应用程序)。

    我的解决方法是(幸运的是)它仅在使用不是 FQDN 的服务器名称(例如 myserver)时自动检测本地 Intranet 区域 - 但使用完整的 A

    【讨论】:

      【解决方案4】:

      当我在我的 Angular 应用程序中启动多个数据加载时,我也遇到了这个问题。

      我通过检测浏览器来解决这个问题,如果是 IE,则根据调用索引将每个请求延迟 50 毫秒:

      return $q(function(resolve, reject) {
       var delay = self.widget.useDelayLoading ? self.widget.index * 50 : 0;
      
       setTimeout(function() {
         restService.genericApi(self.widget.url, false).queryPost(json).$promise
          .then(
           function(r) { resolve(r); }, 
           function(e) { reject(e); }
          );
       }, delay);
      });
      

      有趣的是,当我使用$timeout 时,我不得不将延迟增加到 100 毫秒。

      【讨论】:

      • 不幸的是,这似乎只在刷新页面而不是在初始页面加载时才有效。还在调查中……
      • 您找到解决方案了吗?我有同样的问题,并为每个请求实施了一个稍微随机的延迟,并逐渐延迟了重试。这有帮助,但并没有完全解决问题
      【解决方案5】:

      我们在使用 Angular 和 Web api 时遇到过类似的问题。当系统尝试访问启用了 Windows 身份验证的根级别的某些资源时,会发生问题。在我们的例子中,应用程序试图从 IIS 根目录获取网站图标。一旦这个请求被未经授权,IE 将尝试获取带有协商标头的资源;虽然它再次失败。但是从现在开始,IE 一直发送协商标头而不是我们的不记名令牌。这是由于 IE 中的设置,我认为它位于 Internet 选项 -> 高级选项卡 -> 在安全部分中启用集成 Windows 身份验证(不确定,我忘记了确切的内容)。

      修复要么给予对根级别的匿名访问,要么给予应用试图访问的资源位置(错误的选项)或有 document.execCommand('ClearAuthenticationCache', false);在 app.js 文件中。

      【讨论】:

      • document.execCommand('ClearAuthenticationCache', false);在 app.js 文件中。 你是什么意思?我的理解是,代码仅与清除基本身份验证的身份验证缓存有关,与 Windows 无关。你会把这些代码放在你的 Angular 应用程序的什么地方?它必须在您向 IWA 受保护资源请求之后,但在您向匿名资源请求之前,对吗?
      • @PeterM - 我的意思是在你的主模块/控制器中拥有该代码。 AFAIK,一旦请求达到 401(当尝试访问使用 Windows 身份验证保护的资源时),IE 会尝试使用协商令牌再次访问该资源。之后,IE 缓存该令牌并为所有后续请求发送该令牌。这是由于我在答案中提到的 IE 中的设置(如果我没记错的话)。您能否验证网络选项卡中的行为? 401 错误请求后,协商令牌是否会继续?
      • @PeterM - 即使拥有 clearCache 代码,您仍然面临问题吗?
      • 我还没有尝试过 clearCache 代码,因为我不确定将它放在哪里。我们加载了一些受 IWA 保护的资源(html、js),但我们也从受 IWA 保护的资源中获取 API 的身份验证令牌,因此知道何时清除凭证缓存很棘手。此外,感觉我们最终会收到更多登录提示。我会在接下来的几天内尝试一下
      • @PeterM - 我想说只是将它保存在全局范围内,在整个应用程序范围内都可用的主模块中。不用每次都清零,一次性配置。
      【解决方案6】:

      在我的例子中,IE 交替发送一个错误的请求,然后在第二次尝试时发出一个好的请求,然后再次发出一个错误的请求,依此类推。

      在尝试了几种导致 IE 重试的方法后 - 在 Location 标头中返回具有相同请求 url 的 307(临时重定向)似乎解决了该问题。

      例如请求“http://myUrl/api/service/

      HTTP 307 Temporary Redirect
      Location: http://myUrl/api/service/
      

      IE 使用正确的数据重试调用。

      编辑:这种方法可能很危险,因为它可能会创建一个无限循环。一种可能的解决方案是在 Location 标头中返回一些计数器作为 url 的一部分,并在再次收到调用时对其进行分析。

      【讨论】:

        猜你喜欢
        • 2019-02-26
        • 2014-01-14
        • 2013-03-23
        • 2021-03-02
        • 1970-01-01
        • 2012-01-16
        • 2014-05-08
        • 2019-11-20
        • 2015-01-27
        相关资源
        最近更新 更多