更新时间:2021-12-26 07:12:35
不幸的是我已确定(通过分析WCF参考源$ C $ c和提琴手工具嗅探HTTP会话的帮助下),这是一个错误WCF的堆栈。
Unfortunately I have determined (by analysing the WCF reference source code and the help of the Fiddler tool for HTTP session sniffing) that this is a bug in the WCF stack.
,我发现我的WCF服务是不像使用基本身份验证任何其他网站的行为。
Using Fiddler, I noticed that my WCF service was behaving unlike any other web site which uses Basic authentication.
需要明确的是,这是会发生什么:
To be clear, this is what SHOULD happen:
GET
请求而不知道密码,甚至必要的。 401未授权
状态请求,其中包括约含接受身份验证信息的 WWW验证
头方法。 GET
要求,包括与凭证相应的验证
头。 200 OK
和网页响应。响应401授权
,包括它做了同样的 WWW验证
头步骤#2。GET
request with no knowledge that a password is even needed.401 Unauthorized
status and includes a WWW-Authenticate
header containing information about acceptable authentication methods.GET
request and includes appropriate Authentication
header with the credentials.200 OK
and the web page.
If the credentials were wrong, the web server responds with 401 Unauthorized
and includes the same WWW-Authenticate
header that it did in Step #2.什么竟是我的WCF服务发生是这样的:
What was ACTUALLY happening with my WCF service was this:
GET
请求而不知道密码,甚至必要的。验证
头,盲目将拒绝一个 401未授权
状态请求,其中包括一个 WWW验证
头。所有正常为止。 GET
的要求,包括适当的验证
头。 200 OK
响应。一切皆好。响应403禁止
,不包括任何附加头,如 WWW验证
GET
request with no knowledge that a password is even needed.Authentication
header in the request and blindly rejects request with a 401 Unauthorized
status and includes a WWW-Authenticate
header. All normal so far.GET
request including the appropriate Authentication
header.200 OK
. All is fine.
If the credentials were wrong however, WCF responds with 403 Forbidden
and does not include any additional headers such as WWW-Authenticate
.在浏览器中得到 403禁止
状态并不认为这是一个失败的认证尝试。此状态code是为了告知浏览器,它试图访问的URL是关闭的限制。它不涉及以任何方式向认证。这可怕的一面影响,当用户键入他们的用户名/密码错误(和服务器403拒绝),那么Web浏览器不会重新提示用户再次输入其凭据。事实上,Web浏览器认为认证成功,因此对于存储在会议休息!
When the browser gets the 403 Forbidden
status it does not perceive this to be a failed authentication attempt. This status code is intended to inform the browser that the URL it tried to access is off limits. It doesn't relate to authentication in any way. This has the terrible side affect that when the user types their username/password incorrectly (and the server rejects with 403) then the web browser doesn't reprompt the user to type their credentials again. In fact the web browser believes authentication has succeeded and so stores those credentials for the rest of the session!
考虑到这一点,我希望澄清:
With this in mind, I sought clarification:
在RFC 2617(http://www.faqs.org/rfcs/rfc2617.html#ixzz0eboUfnrl)没有任何地方提到了 403禁止
状态$的C $℃。事实上,它实际上已经就此事说的是以下内容:
The RFC 2617 (http://www.faqs.org/rfcs/rfc2617.html#ixzz0eboUfnrl) does not mention anywhere the use of the 403 Forbidden
status code. In fact, what it actually has to say on the matter is the following:
如果原始服务器不希望
接受与发送的凭据
请求时,它应该返回一个401
(未授权)的回应。响应
必须包含一个WWW-Authenticate头
含有至少一个字段
适用于(可能是新的)质询
所请求的资源。
If the origin server does not wish to accept the credentials sent with a request, it SHOULD return a 401 (Unauthorized) response. The response MUST include a WWW-Authenticate header field containing at least one (possibly new) challenge applicable to the requested resource.
WCF确实没有这些。它既不正确发送 401未授权
状态code。它也不包括 WWW验证
头。
WCF does neither of these. It neither correctly sends an 401 Unauthorized
status code. Nor does it include a WWW-Authenticate
header.
现在找到了WCF源$ C $ C内冒烟的枪:
Now to find the smoking gun within the WCF source code:
我发现,在的Htt prequestContext
类是调用方法 ProcessAuthentication
,其中包含以下(节选):
I discovered that in the HttpRequestContext
class is a method called ProcessAuthentication
, which contains the following (excerpt):
if (!authenticationSucceeded)
{
SendResponseAndClose(HttpStatusCode.Forbidden);
}
我捍卫微软的很多事情,但这是站不住脚的。
I defend Microsoft on a lot of things but this is indefensible.
幸运的是,我有它的工作到一个可接受的水平。它只是意味着,如果用户不小心输入自己的用户名/密码不正确,然后再弄尝试的唯一方法是完全关闭其Web浏览器并重新启动它重试。这一切都是因为WCF是的不的响应与认证尝试失败 401未授权
和 WWW验证
头按规范。
Fortunately, I have got it working to an "acceptable" level. It just means that if the user accidently enters their username/password incorrectly then the only way to get another attempt is to fully close their web browser and restart it to retry. All because WCF is not responding to the failed authentication attempt with a 401 Unauthorized
and a WWW-Authenticate
header as per the specification.