html ajax实现ntlm,jquery - Getting an NTLM Challenge from an AJAX POST on just one page - Stack Overfl...

在ASP.NET MVC4应用中遇到特定页面的jQuery AJAX POST请求触发NTLM重新认证的问题,表现为浏览器无限循环请求用户名密码。问题核心在于请求头缺少Connection: keep-alive。
摘要由CSDN通过智能技术生成

Quite the mystery here. I have an ASP.NET MVC 4 web application using Windows Authentication that has been maintained for over 18 months without issue. Recently, it was deployed to a fresh site and I've encountered the following, very strange behavior.

I am using a jQuery 1.8.2 $.ajax call to POST data to the server endpoints to update data. This works just fine except on one page, where the AJAX POST triggers a new NTLM Negotiation. The same problem is exhibited in Chrome, IE, and Firefox. While the issue is the same in all the browsers, it manifests itself in slightly different ways:

Firefox : Received a 401 Challenge response from the server and brings up a username/password dialog asking for credential in an infinite loop. Canceling the credential checks causes the request to fail with an Unauthorized response.

IE : No response from the server and the request status shows as "(Aborted)" in the Network monitor

Chrome : No response from the server and the request status shows a "(failure)" in the Network monitor.

The core issue seems to be that the Connection: keep-alive header is not being sent with the problematic AJAX request, but is in the other cases. However, the underlying JavaScript code is nearly identical, and the AJAX calls function properly in a development environment that is also set up to use Windows authentication.

Also, attempting the set the Connection request header in the beforeSend callback has no effect.

Any insights into the root of the problem, or ways to isolate whatever difference exists between the two AJAX POSTs are most appreciated.

Working Code and Request Headers

$.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

Failing Code and Request Headers

$.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

I have also looked at the network process in the Chrome chrome://net-internals/#events viewer. Here is the event log from the failed request at the point it deviates from the successful one. Where the failed request gets an "HTTP/1.1 401 Unauthorized" the successful request gets an "HTTP/1.1 200 OK" response, presumably due to the presence of the Connection: keep-alive header.

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

Edit

Playing around with different request from the console gives the following table of results (under Chrome). The current base URL is http://IPAddress

/app/topic/item and all test simply execute an $.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] |

+--------------------------------------+----------------------------+

Because the error only affects a subset of the POST action methods in one controller, I had initially thought this was a server-side issue, but after uncovering the issue of the missing Connection header, it actually appear to be a client-side issue. Exactly how the problem is triggered remains a mystery to me.

I did also verify that the Response headers for the working page and the problematic page are the same. Most relevant, the Persistent-Auth: true header is always returned in both cases.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值