且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

自承载WCF REST服务和基本身份验证

更新时间: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:


  1. 浏览器发送 GET 请求而不知道密码,甚至必要的。

  2. Web服务器拒绝了 401未授权状态请求,其中包括约含接受身份验证信息的 WWW验证头方法。

  3. 浏览器会提示用户输入凭据。

  4. 浏览器重新发送 GET 要求,包括与凭证相应的验证头。

  5. 如果凭据是正确的,在Web服务器 200 OK 和网页响应。
    如果凭据是错误的,在Web服务器响应401授权,包括它做了同样的 WWW验证头步骤#2。

  1. Browser sends GET request with no knowledge that a password is even needed.
  2. Web server rejects request with a 401 Unauthorized status and includes a WWW-Authenticate header containing information about acceptable authentication methods.
  3. Browser prompts user to enter credentials.
  4. Browser resends GET request and includes appropriate Authentication header with the credentials.
  5. If the credentials were correct, the web server responds with 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:


  1. 浏览器发送 GET 请求而不知道密码,甚至必要的。

  2. WCF注意到有请求没有验证头,盲目将拒绝一个 401未授权状态请求,其中包括一个 WWW验证头。所有正常为止。

  3. 浏览器会提示用户输入凭据。尚正常。

  4. 浏览器重新发送 GET 的要求,包括适当的验证头。

  5. 如果凭据是正确的,在Web服务器 200 OK 响应。一切皆好。
    如果凭据但是错了,WCF与响应403禁止,不包括任何附加头,如 WWW验证

  1. Browser sends GET request with no knowledge that a password is even needed.
  2. WCF notices there is no Authentication header in the request and blindly rejects request with a 401 Unauthorized status and includes a WWW-Authenticate header. All normal so far.
  3. Browser prompts user for credentials. Still normal.
  4. Browser resends GET request including the appropriate Authentication header.
  5. If the credentials were correct, the web server responds with 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.