页面使用NTLM身份验证时引用外部脚本失败

时间:2016-09-12 11:21:50

标签: javascript c# authentication web ntlm

在为Intranet网页合并NTLM身份验证时,我们遇到了以下问题。

我们的网页代码包含一些在标题

中引用的javascript文件
<link rel="stylesheet" type="text/css" href="./jsoneditor.css">
<script type="text/javascript" src="./jsoneditor.js"></script>
<script type="text/javascript" src="./lib/ace/ace.js"></script>
<script type="text/javascript" src="./lib/ace/mode-json.js"></script>
<script type="text/javascript" src="./lib/ace/theme-textmate.js"></script>
<script type="text/javascript" src="./lib/ace/theme-jsoneditor.js"></script>
<script type="text/javascript" src="./lib/jquery.js"></script>
<script type="text/javascript" src="./lib/jsonlint/jsonlint.js"></script>

这些文件中的某些功能稍后会在页面正文中调用。

它是如何正常工作的(没有身份验证)。在打开页面时,会发出index.html的请求,然后是对引用的每个资源的单独请求:

Requests seen in Firebug without authentication

它们按引用顺序处理(您可以看到<script>标记中的文件顺序与请求顺序相同。.html文件是如何处理的?

Html file processing

因此,请求资源并且解析已停止,直到响应到来。然后它继续执行,如果有的话,并移动到引用的下一个脚本。

因此,如果需要一些需要的命令,例如ace.js需要首先加载jsoneditor.js,这是确保的。

好的,这是一个介绍,现在是NTLM身份验证。它改变了由于NTLM握手而获取资源的方式。它看起来像这样:

1: C  --> S   GET ...
2: C <--  S   401 Unauthorized, WWW-Authenticate: NTLM
3: C  --> S   GET ..., Authorization: NTLM <base64-encoded type-1-message>
4: C <--  S   401 Unauthorized, WWW-Authenticate: NTLM <base64-encoded type-2-message>
5: C  --> S   GET ..., Authorization: NTLM <base64-encoded type-3-message>
6: C <--  S   200 Ok

因此,针对单个资源发送了3个请求,而不是一个。

为什么重要?因为发送外部资源请求的网页解析器并不关心,如果它实际上已经交付,它只是等待响应(在我们的例子中是401)并转移到下一个脚本的加载。最终,所有文件都来了,但是(1)订单没有强制执行,(2)可以运行正文中的函数调用,即使资源尚未到达(成功的200响应)。并且它可能导致抛出javascript异常并且页面未被加载。

Requests seen in Firebug with NTLM authentication

您可以看到第一次请求的正确顺序,状态代码为200的响应会混合在一起。

目前我们已经找到了两个解决方案,但没有一个能让我们满意:

  1. 执行正文中的javascript函数时,执行一些延迟(当然不是好方法)
  2. 将所有javascript代码移至index.html而不是引用外部资源,从代码角度来看这不是很好,但可以确保所有内容都按预期运行。
  3. 不幸的是,NTLM被设计为单独验证每个请求,这使案件稍微复杂化。在我们的方案中,无法将NTLM更改为其他身份验证。

    有没有办法以更优雅的方式解决问题?

    为了解决这个问题,我们使用.NET HttpListener类作为主机。

1 个答案:

答案 0 :(得分:0)

对于s production app,您应该在部署之前运行构建过程,以便在任何情况下连接和缩小脚本。这将消除订单问题,因为它们全部作为一个文件传递,内容按正确的顺序排列。