为什么我的REST服务.NET客户端发送的每个请求没有认证头,然后与认证头重试吗? [英] Why would my REST service .NET clients send every request without authentication headers and then retry it with authentication header?

查看:128
本文介绍了为什么我的REST服务.NET客户端发送的每个请求没有认证头,然后与认证头重试吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们碰巧来运行要求客户端使用的基本的验证API一个REST Web服务。我们精心设计了一个集各种语言整齐的样品展示如何使用我们的服务接口。现在我回顾了服务的IIS日志,看到下面的模式会频繁出现:

We happen to run a REST web service with API requiring that clients use Basic authentication. We crafted a set of neat samples in various languages showing how to interface with our service. Now I'm reviewing IIS logs of the service and see that the following pattern happens quite often:


  • 收到请求时,获取与HTTP $ C $拒绝ç401

  • 相同的请求重新发送和成功

它看起来像第一个请求没有的授权的头部信息,然后第二个是用正确的报头和发送成功。大多数时候,日志记录包含用户代理,这是我们种到我们的.NET示例相同的字符串。

which looks like the first request is sent without Authorization headers and then the second one is sent with the right headers and succeeds. Most of the time the log record contains "user-agent" which is the same string we planted into our .NET sample.

所以,我认为这个问题是一个只有.NET程序。所以我想用户以某种方式修改了code或写自己白手起家的问题不在于我们的样本code转载。

So I assume the problem is with .NET programs only. The problem is not reproduced with our sample code so I assume the users somehow modified the code or wrote their own from scratch.

我们试图联系的用户,但显然他们不希望时间投入到研究。因此,它会是不错的找到最可能的情况是什么导致.NET程序的这种行为。

We tried contacting the users but apparently they don't want to invest time into research. So it'd be nice to find what the most likely scenario is which leads to this behavior of .NET programs.

为什么他们会这么做?为什么他们不重视在第一次尝试的头?

Why would they do this? Why would they not attach the headers on the first attempt?

推荐答案

这是默认行为的HttpClient 的HttpWebRequest 其中露出下面的方式类

This is the default behavior of HttpClient and HttpWebRequest classes which is exposed the following way.

注:以下文字解释了造成问题描述的问题最理想的行为。最有可能你不应该写你的code这样。相反下方滚动修正code

Note: Below text explains suboptimal behavior causing the problem described in the question. Most likely you should not write your code like this. Instead scroll below to the corrected code

在这两种情况下,实例化一个 NetworkCredenatial 对象,并在那里设置用户名和密码

In both cases, instantiate a NetworkCredenatial object and set the username and password in there

var credentials = new NetworkCredential( username, password );

如果您使用的HttpWebRequest - 设置 .Credentials 属性:

If you use HttpWebRequest - set .Credentials property:

webRequest.Credentials = credentials;

如果您使用的HttpClient - 凭据传递对象到 HttpClientHandler (改变$ C $从的这里):

If you use HttpClient - pass the credentials object into HttpClientHandler (altered code from here):

var client = new HttpClient(new HttpClientHandler() { Credentials = credentials })

然后运行提琴手并启动请求。您将看到以下内容:

Then run Fiddler and start the request. You will see the following:


  • 将请求发送无的授权的标题

  • 服务与HTTP 401答复和的 WWW身份验证:基本境界=UrRealmHere

  • 的请求是适当的授权的头反感(和成功)

  • the request is sent without Authorization header
  • the service replies with HTTP 401 and WWW-Authenticate: Basic realm="UrRealmHere"
  • the request is resent with proper Authorization header (and succeeds)

此行​​为是这里解释 - 客户端不事先知道服务需要的基本的并尝试协商身份验证协议(如果该服务需要的摘要的发送的基本的开放头是无用的,会损害客户端)。

This behavior is explained here - the client doesn't know in advance that the service requires Basic and tries to negotiate the authentication protocol (and if the service requires Digest sending Basic headers in open is useless and can compromise the client).

注:这里不理想的行为解释两端,更好的方法是解释。最有可能的,你应该使用code从下方而不是code从上面。

Note: Here suboptimal behavior explanation ends and better approach is explained. Most likely you should use code from below instead of code from above.

有关情况下,当据了解,该服务需要的基本的额外要求可以消除通过以下方式:

For cases when it's known that the service requires Basic that extra request can be eliminated the following way:

不要设置 .Credentials ,而不是使用code手动的此处。恩code中的用户名和密码:

Don't set .Credentials, instead add the headers manually using code from here. Encode the username and password:

var encoded = Convert.ToBase64String( Encoding.ASCII.GetBytes(
    String.Format( "{0}:{1}", username, password ) ) );

在使用的HttpWebRequest 将其添加到标头:

When using HttpWebRequest add it to the headers:

request.Headers.Add( "Authorization", "Basic " + encoded );

和使用时,的HttpClient 添加到默认标题:

and when using HttpClient add it to default headers:

client.DefaultRequestHeaders.Authorization =
    new AuthenticationHeaderValue( "Basic", encoded );

当你这样做的请求与正确的授权头每次发送。请注意,您不应设置 .Credentials ,否则,如果用户名或密码错误相同的请求将被发送这两个时间两次错误的证书,当然还有两次产生HTTP 401。

When you do that the request is sent with the right authorization headers every time. Note that you should not set .Credentials, otherwise if the username or password is wrong the same request will be sent twice both time with the wrong credentials and both times of course yielding HTTP 401.

这篇关于为什么我的REST服务.NET客户端发送的每个请求没有认证头,然后与认证头重试吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆