大家早上好,
我有一个使用经典 ASP 的 Web 应用程序,托管在 IIS 7.5 上。我需要创建一个 word 文档并流回客户端进行显示,但是当文档流式传输到响应中时(IIS 设置?)导致 401 错误 - 我无法追踪它。
一位同事非常友好地为我提供了一些处理文档构建和流式传输的 C++ 代码以及一个构建 COM 对象并进行调用等的 ASP 页面。
该文档作为模板在我的 ASP 应用程序外部的 IIS 虚拟目录中开始使用。我们制作一个副本,执行一些查找和替换操作,然后使用正确的 MIME 类型将其流式传输到响应中,以便浏览器以它认为合适的方式处理它。
似乎一旦发生流式传输(通过调用ASPTypeLibrary::IResponsePtr piResponse->BinaryWrite()
),就会发回 401 响应,直到那一刻响应看起来很好。
该站点使用表单身份验证,此时我已登录,我在提琴手中看到的请求肯定具有有效的会话数据,并且站点的其余部分对我的身份验证感到满意。
有任何想法吗?(他带着绝望的语气问道)
ps 我意识到我没有列出所有的代码,如果有帮助的话我可以......
剧情变厚了……
我已经成功地使用 ASP 页面使用和ADODB.Stream
对象将文件流式传输到输出中。
当这成功时,Fiddler 拾取两个 HTTP 请求/响应;第一个请求返回 401,然后浏览器发送另一个带有不同 cookie 数据的请求,返回成功结果。
当使用我的 COM 对象时,会发生两个请求,但第二个请求也会收到 401...
指向与 COM 对象有关的一些安全设置?我没有添加到 COM 对象的响应中?
根据我对 Eric 的回复,我的同事施展了一些魔法,让事情顺利进行,但我仍然有点困惑为什么会这样……
魔术阿尔改变的那一行是这样的:
piResponse->AddHeader( _T("Content-Length"), (LPCTSTR)Length );
在建立响应时调用它,他所做的就是将其注释掉。
显然,他注意到由 写入的BinaryWrite
长度比文件的长度大 13 个字节。他告诉我这可能是因为它正在写出Variant
它给出的保留字块。
所以响应头有点乱,结果是我忽略的提琴手中的 HTTP 违规错误,并且在客户端和 COM 对象之间的某个地方,损坏的 200 响应被替换为 401。
我想这个故事的寓意是您应该始终注意提琴手的错误并确保您的错误Content-Length
是正确的。
我的新问题是为什么 401?为什么不是500?什么可能会抛出这个?它来自 IIS 吗?
这是用于交换的 HTTP 文本提琴手注册:
GET GET [The page address - its on localhost and is an ASP page] HTTP/1.1
Accept: text/html, application/xhtml+xml, */*
Accept-Language: en-GB
User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0)
Accept-Encoding: gzip, deflate
Connection: Keep-Alive
Host: localhost
Cookie: SessionUID={E41F5378-FBE2-475E-8F9A-6416AFE2BAA0}; DisplayMethod=0; ShowDataTips=1; LOGONUSER={UserName Info}ASPSESSIONIDQARAQRBD={Session ID} Authorization: Negotiate YH8GBisGAQUFAqB1MHOgMDAuBgorBgEEAYI3AgIKBgkqhkiC9xIBAgIGCSqGSIb3EgECAgYKKwYBBAGCNwICHqI/BD1OVExNU1NQAAEAAACXsgjiCwALADIAAAAKAAoAKAAAAAYBsR0AAAAPRE9DREVWLUpDV0RFVkVMT1BNRU5U
HTTP/1.1 401 Unauthorized
Content-Type: text/html; charset=us-ascii
Server: Microsoft-HTTPAPI/2.0
WWW-Authenticate: Negotiate oYIBYTCCAV2gAwoBAaEMBgorBgEEAYI3AgIKooIBRgSCAUJOVExNU1NQAAIAAAAWABYAOAAAABXCieJQEtMwe36vajD3zwEAAAAA9AD0AE4AAAAGAbEdAAAAD0QARQBWAEUATABPAFAATQBFAE4AVAACABYARABFAFYARQBMAE8AUABNAEUATgBUAAEAFABEAE8AQwBEAEUAVgAtAEoAQwBXAAQAOABEAGUAdgBlAGwAbwBwAG0AZQBuAHQALgBEAG8AYwB1AG0AYQB0AGkAbwBuAC4AYwBvAC4AdQBrAAMATgBEAE8AQwBEAEUAVgAtAEoAQwBXAC4ARABlAHYAZQBsAG8AcABtAGUAbgB0AC4ARABvAGMAdQBtAGEAdABpAG8AbgAuAGMAbwAuAHUAawAFACAARABvAGMAdQBtAGEAdABpAG8AbgAuAGMAbwAuAHUAawAHAAgAKRk7jhfZzQEAAAAA
Date: Thu, 13 Dec 2012 09:52:25 GMT
Content-Length: 341
Proxy-Support: Session-Based-Authentication
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN""http://www.w3.org/TR/html4/strict.dtd">
<HTML><HEAD><TITLE>Not Authorized</TITLE>
<META HTTP-EQUIV="Content-Type" Content="text/html; charset=us-ascii"></HEAD>
<BODY><h2>Not Authorized</h2>
<hr><p>HTTP Error 401. The requested resource requires user authentication.</p>
</BODY></HTML>
------------------------------------------------------------------
GET [The page address - its on localhost and is an ASP page] HTTP/1.1
Accept: text/html, application/xhtml+xml, */*
Accept-Language: en-GB
User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0)
Accept-Encoding: gzip, deflate
Connection: Keep-Alive
Cookie: SessionUID={E41F5378-FBE2-475E-8F9A-6416AFE2BAA0}; DisplayMethod=0; ShowDataTips=1; LOGONUSER={UserName Info}ASPSESSIONIDQARAQRBD={Session ID}
Authorization: Negotiate oXcwdaADCgEBoloEWE5UTE1TU1AAAwAAAAAAAABYAAAAAAAAAFgAAAAAAAAAWAAAAAAAAABYAAAAAAAAAFgAAAAAAAAAWAAAABXCiOIGAbEdAAAAD4GPyFfTAkcs1KpJqG4eT0ujEgQQAQAAAPUXp1AtIpqEAAAAAA==
Host: localhost
HTTP/1.1 401 Unauthorized
Cache-Control: private
Content-Type: text/html; charset=utf-8
Server: Microsoft-IIS/7.5
WWW-Authenticate: Negotiate
WWW-Authenticate: NTLM
X-Powered-By: ASP.NET
Date: Thu, 13 Dec 2012 09:52:27 GMT
Content-Length: 6630
Proxy-Support: Session-Based-Authentication
<HTML Page telling you about the error which gets displayed when you cancel the authentication dialog.>