问题描述
我创建了一个自承载WCF REST服务(与WCF REST入门套件preVIEW 2一些额外的)。这是所有工作的罚款。
I've created a self-hosted WCF REST service (with some extra's from WCF REST Starter Kit Preview 2). This is all working fine.
我现在正试图基本身份验证添加到服务。但我打的WCF栈,$ P $从这样pventing我一些相当大的障碍。
I'm now trying to add Basic authentication to the service. But I'm hitting some rather large roadblocks in the WCF stack which is preventing me from doing this.
看来,的HttpListener
(其中自承载WCF服务在WCF的堆栈低水平内部使用)被挡住了我的企图插入<$ C $在自生成 401未授权
响应C> WWW验证头。为什么呢?
It appears that the HttpListener
(which self-hosted WCF services use internally at a low level in the WCF stack) is blocking my attempts to insert a WWW-Authenticate
header on a self-generated 401 Unauthorized
response. Why?
我可以得到验证,如果我忘记了这个 WWW验证
头(这似乎微软并没有为好)工作。但是,这是个问题。如果我没有发回一个 WWW验证
头则Web浏览器无法显示其标准的登录对话框。用户只会面临一个 401未授权
错误页面没有办法实际登录。
I can get the authentication working if I forget about this WWW-Authenticate
header (which it seems Microsoft did as well). But that's the issue. If I don't send back a WWW-Authenticate
header then the web browser won't display its standard "logon" dialog. The user will merely be faced with a 401 Unauthorized
error page with no way to actually log on.
REST服务应该是(对GET请求级别以及至少)计算机和人类的访问。因此,我觉得WCF REST是不是在这里REST的基本组成部分规定。有没有人同意我的观点?
REST services should be accessible to both computers and humans (well at least on the GET request level). Therefore, I feel that WCF REST is not complying with a fundamental part of REST here. Does anyone agree with me?
有没有人有基本身份验证与自承载WCF REST服务工作吗?如果是这样,你是怎么做到的?
Has anyone got Basic authentication working with a self-hosted WCF REST service? If so, how did you do it?
PS:很显然,我的意图使用不安全的基本身份验证都在premise我也是会得到HTTPS / SSL对我的服务工作压力太大。但是,这是另一回事了。
PS: Obviously my intentions to use unsecure Basic authentication are on the premise that I'd also get HTTPS/SSL working for my service too. But that's another matter.
PPS:我试过WCF REST的Contrib(HTTP://wcfrestcontrib.$c$cplex.com/),并且具有完全相同的问题。看来这个库尚未在自托管方案进行了测试。
PPS: I've tried WCF REST Contrib (http://wcfrestcontrib.codeplex.com/) and that has exactly the same issue. It appears this library has not been tested in self-hosted scenarios.
感谢。
推荐答案
不幸的是我已确定(通过分析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
请求而不知道密码,甚至必要的。 - Web服务器拒绝了
401未授权
状态请求,其中包括约含接受身份验证信息的WWW验证
头方法。 - 浏览器会提示用户输入凭据。
- 浏览器重新发送
GET
要求,包括与凭证相应的验证
头。 - 如果凭据是正确的,在Web服务器
200 OK
和网页响应。
如果凭据是错误的,在Web服务器响应401授权
,包括它做了同样的WWW验证
头步骤#2。
- Browser sends
GET
request with no knowledge that a password is even needed. - Web server rejects request with a
401 Unauthorized
status and includes aWWW-Authenticate
header containing information about acceptable authentication methods. - Browser prompts user to enter credentials.
- Browser resends
GET
request and includes appropriateAuthentication
header with the credentials. - 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 with401 Unauthorized
and includes the sameWWW-Authenticate
header that it did in Step #2.
什么竟是我的WCF服务发生是这样的:
What was ACTUALLY happening with my WCF service was this:
- 浏览器发送
GET
请求而不知道密码,甚至必要的。 - WCF注意到有请求没有
验证
头,盲目将拒绝一个401未授权
状态请求,其中包括一个WWW验证
头。所有正常为止。 - 浏览器会提示用户输入凭据。尚正常。
- 浏览器重新发送
GET
的要求,包括适当的验证
头。 - 如果凭据是正确的,在Web服务器
200 OK
响应。一切皆好。
如果凭据但是错了,WCF与响应403禁止
,不包括任何附加头,如WWW验证
- Browser sends
GET
request with no knowledge that a password is even needed. - WCF notices there is no
Authentication
header in the request and blindly rejects request with a401 Unauthorized
status and includes aWWW-Authenticate
header. All normal so far. - Browser prompts user for credentials. Still normal.
- Browser resends
GET
request including the appropriateAuthentication
header. - If the credentials were correct, the web server responds with
200 OK
. All is fine.If the credentials were wrong however, WCF responds with403 Forbidden
and does not include any additional headers such asWWW-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头
含有至少一个字段
适用于(可能是新的)质询
所请求的资源。
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.
这篇关于自承载WCF REST服务和基本身份验证的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!