Mixing Integrated Authentication and Anonymous Authentication with PreAuthenticated = true doesn’t w...

文章详细描述了一个.NET框架在预认证下进行PUT/POST请求时出现空实体体的问题,以及如何通过调整代码实现优化请求数量并避免错误。

This StackOverflow question indicate that it is half a bug and half a feature, but that it sure as hell looks like a bug to me.

Let us assume that we have a couple of endpoints in our application, called http://localhost:8080/secure and http://localhost:8080/public. As you can imagine, the secure endpoint is… well, secure, and requires authentication. The public endpoint does not.

We want to optimize the number of request we make, so we specify PreAuthenticated = true; And that is where all hell break lose.

The problem is that it appears that when using request with entity body (in other words, PUT / POST) with PreAuthenticate = true, the .NET framework will issue a PUT / POST request with empty body to the server. Presumably to get the 401 authentication information. At that point, if the endpoint that it happened to have reached is public, it will be accepted as a standard request, and processing will be tried. The problem here is that it has an empty body, so that has a very strong likelihood of failing.

This error cost me a day and a half or so. Here is the full repro:

static void Main() {     new Thread(Server)     {         IsBackground = true     }.Start();      Thread.Sleep(500); // let the server start      bool secure = false;     while (true)     {         secure = !secure;         Console.Write("Sending: ");         var str = new string('a', 621);         var req = WebRequest.Create(secure ? "http://localhost:8080/secure" : "http://localhost:8080/public");         req.Method = "PUT";          var byteCount = Encoding.UTF8.GetByteCount(str);         req.UseDefaultCredentials = true;         req.Credentials = CredentialCache.DefaultCredentials;         req.PreAuthenticate = true;         req.ContentLength = byteCount;          using(var stream = req.GetRequestStream())         {             var bytes = Encoding.UTF8.GetBytes(str);             stream.Write(bytes, 0, bytes.Length);             stream.Flush();         }          req.GetResponse().Close();      }  }

And the server code:

public static void Server() {     var listener = new HttpListener();     listener.Prefixes.Add("http://+:8080/");     listener.AuthenticationSchemes = AuthenticationSchemes.IntegratedWindowsAuthentication | AuthenticationSchemes.Anonymous;     listener.AuthenticationSchemeSelectorDelegate = request =>     {          return request.RawUrl.Contains("public") ? AuthenticationSchemes.Anonymous : AuthenticationSchemes.IntegratedWindowsAuthentication;     };      listener.Start();      while (true)     {         var context = listener.GetContext();         Console.WriteLine(context.User != null ? context.User.Identity.Name : "Anonymous");         using(var reader = new StreamReader(context.Request.InputStream))         {             var readToEnd = reader.ReadToEnd();             if(string.IsNullOrEmpty(readToEnd))             {                 Console.WriteLine("WTF?!");                 Environment.Exit(1);             }         }          context.Response.StatusCode = 200;         context.Response.Close();     } } 

If we remove pre authenticate is set to false, everything works, but then we have twice as many requests. The annoying thing is that if it would be trying to authenticate to a public endpoint, nothing would happen, if it were sending the bloody entity body along as well.

This is quite annoying.

转载于:https://www.cnblogs.com/shihao/archive/2012/01/12/2320680.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值