【发布时间】:2015-07-07 20:12:27
【问题描述】:
这里很神秘。我有一个使用 Windows 身份验证的 ASP.NET MVC 4 Web 应用程序,该应用程序已维护超过 18 个月而没有问题。最近,它被部署到一个新站点,我遇到了以下非常奇怪的行为。
我正在使用 jQuery 1.8.2 $.ajax 调用将数据发布到服务器端点以更新数据。这工作得很好,除了在一个页面上,AJAX POST 触发新的 NTLM 协商。同样的问题也出现在 Chrome、IE 和 Firefox 中。虽然问题在所有浏览器中都是相同的,但其表现方式略有不同:
- Firefox:收到来自服务器的 401 Challenge 响应,并在无限循环中弹出用户名/密码对话框,要求提供凭据。取消凭据检查会导致请求失败并返回未经授权的响应。
- IE:服务器没有响应,请求状态在网络监视器中显示为“(中止)”
- Chrome:服务器没有响应,请求状态在网络监视器中显示“(失败)”。
核心问题似乎是 Connection: keep-alive 标头没有与有问题的 AJAX 请求一起发送,但在其他情况下。但是,底层 JavaScript 代码几乎相同,并且 AJAX 调用在也设置为使用 Windows 身份验证的开发环境中正常运行。
另外,尝试在beforeSend 回调中设置Connection 请求标头无效。
非常感谢您对问题根源的任何见解,或隔离两个 AJAX POST 之间存在的任何差异的方法。
工作代码和请求标头
$.ajax({
url: url,
type: "POST",
data: $("#myForm").serialize(),
cache: false,
success: function (response) {
}
});
Accept:*/*
Accept-Encoding:gzip, deflate
Accept-Language:en-US,en;q=0.8
Connection:keep-alive
Content-Length:621
Content-Type:application/x-www-form-urlencoded; charset=UTF-8
Host:www.xxx.yyy.zzz
Origin:http://www.xxx.yyy.zzz
Referer:http://www.xxx.yyy.zzz/app/resource/path
User-Agent:Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.135 Safari/537.36
X-Requested-With:XMLHttpRequest
失败的代码和请求标头
$.ajax({
url: url,
type: "POST",
data: data,
cache: false,
success: function (data, status, xhr) {
}
});
WARN: Provisional headers are shown
Accept:*/*
Content-Type:application/x-www-form-urlencoded; charset=UTF-8
Origin:http://www.xxx.yyy.zzz
Referer:http://www.xxx.yyy.zzz/app/resource/item/1
User-Agent:Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.135 Safari/537.36
X-Requested-With:XMLHttpRequest
我还在 Chrome chrome://net-internals/#events 查看器中查看了网络进程。这是失败请求与成功请求不同时的事件日志。失败的请求得到“HTTP/1.1 401 Unauthorized”,成功的请求得到“HTTP/1.1 200 OK”响应,可能是由于Connection: keep-alive 标头的存在。
2303: URL_REQUEST
Start Time: 2015-04-28 13:53:41.788
t=14736 [st= 0] +REQUEST_ALIVE [dt=71]
t=14736 [st= 0] URL_REQUEST_DELEGATE [dt=0]
t=14736 [st= 0] +URL_REQUEST_START_JOB [dt=70]
--> load_flags = 2688000 (BYPASS_DATA_REDUCTION_PROXY | MAYBE_USER_GESTURE | REPORT_RAW_HEADERS | VERIFY_EV_CERT)
--> method = "POST"
--> priority = "LOW"
--> upload_id = "0"
--> url = "http://..."
t=14736 [st= 0] URL_REQUEST_DELEGATE [dt=0]
t=14736 [st= 0] HTTP_CACHE_GET_BACKEND [dt=0]
t=14736 [st= 0] URL_REQUEST_DELEGATE [dt=0]
t=14736 [st= 0] +HTTP_STREAM_REQUEST [dt=0]
t=14736 [st= 0] HTTP_STREAM_REQUEST_BOUND_TO_JOB
--> source_dependency = 2305 (HTTP_STREAM_JOB)
t=14736 [st= 0] -HTTP_STREAM_REQUEST
t=14736 [st= 0] +HTTP_TRANSACTION_SEND_REQUEST [dt=0]
t=14736 [st= 0] HTTP_TRANSACTION_SEND_REQUEST_HEADERS
--> POST ... HTTP/1.1
Host: www.xxx.yyy.zzz
Connection: keep-alive
Content-Length: 105
Accept: */*
Origin: http://www.xxx.yyy.zzz
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.135 Safari/537.36
X-Requested-With: XMLHttpRequest
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
Referer: http://www.xxx.yyy.zzz/app/resource/item/1
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.8
t=14736 [st= 0] HTTP_TRANSACTION_SEND_REQUEST_BODY
--> did_merge = true
--> is_chunked = false
--> length = 105
t=14736 [st= 0] -HTTP_TRANSACTION_SEND_REQUEST
t=14736 [st= 0] +HTTP_TRANSACTION_READ_HEADERS [dt=0]
t=14736 [st= 0] HTTP_STREAM_PARSER_READ_HEADERS [dt=0]
t=14736 [st= 0] HTTP_TRANSACTION_READ_RESPONSE_HEADERS
--> HTTP/1.1 401 Unauthorized
Content-Type: text/html
Server: Microsoft-IIS/7.5
WWW-Authenticate: Negotiate
WWW-Authenticate: NTLM
X-Powered-By: ASP.NET
X-UA-Compatible: IE=9
Date: Tue, 28 Apr 2015 18:53:41 GMT
Content-Length: 1293
编辑
使用来自控制台的不同请求会得到以下结果表(在 Chrome 下)。当前的基本 URL 是 http://IPAddress
/app/topic/item,所有测试只需执行 $.ajax({ url: url, type: 'POST' })
+--------------------------------------+----------------------------+
| URL | Response |
+--------------------------------------+----------------------------+
| http://IP/app/topic/item/1/subitem/1 | net::ERR_INVALID_HANDLE |
| //IP/app/topic/item/1/subitem/1 | net::ERR_INVALID_HANDLE |
| /app/topic/item/1/subitem/1 | net::ERR_INVALID_HANDLE |
| 1/subitem/1 | net::ERR_INVALID_HANDLE |
| 1/foo | 404 (Not Found) [expected] |
| 1 | 302 (Redirect) [expected] |
+--------------------------------------+----------------------------+
因为错误仅会影响一个控制器中POST 操作方法的子集,我最初认为这是服务器端问题,但在发现缺少@987654334 的问题后@ header,它实际上似乎是一个客户端问题。问题的具体触发方式对我来说仍然是个谜。
我还验证了工作页面和问题页面的响应标头是否相同。最相关的是,Persistent-Auth: true 标头在两种情况下都会返回。
【问题讨论】:
-
您是否尝试过从
ajax调用实现error处理程序?你可能会在这里得到一些额外的信息? -
@christiandev 是的。 Chrome 返回 net::ERR_INVALID_HANDLE 错误代码,IE 的错误代码为 12019,记录为 ERROR_INTERNET_INCORRECT_HANDLE_STATE。 Firefox 还会报告“无效句柄”。
-
另外一件事,我添加了与我的所有 [POST] 路由匹配的 [GET] 路由,以防万一这是关于 IE 和 IWA 已知的 GET-before-POST 问题的奇怪表现.这没有效果。
-
我在失败的帖子中看不到任何内容长度。您是否发布任何数据?
-
@Mike 是的,我刚刚验证了 POST 正文中有表单编码数据。标头是 Chrome 开发工具显示的内容,并被标记为临时标头。我捕获了 Fiddler 的请求,它的 Content-Length 为 106,与正文内容匹配。
标签: jquery ajax asp.net-mvc iis windows-authentication