C#HttpListener多种身份验证方案和Chrome

问题描述 投票:0回答:1

好的,这是一个很长的问题,但我认为值得这样做。我们有什么:

  1. 一个示例虚拟C#控制台应用程序,它启动自托管的Owin ASP.Net WebAPI服务(Microsoft.AspNet.WebApi.OwinSelfHost NuGet包): class Program { static void Main(string[] args) { var url = "http://localhost:8080/"; Console.WriteLine($"Starting on {url}"); using (WebApp.Start<Startup>(url)) { Console.WriteLine("Success! Press any key to stop..."); Console.ReadKey(); } } }
  2. OWIN启动课程: class Startup { public void Configuration(IAppBuilder app) { // enable Windows AND Anonymous authentication var listener = app.Properties["System.Net.HttpListener"] as HttpListener; listener.AuthenticationSchemes = AuthenticationSchemes.Anonymous | AuthenticationSchemes.IntegratedWindowsAuthentication; // configure WebAPI var config = new HttpConfiguration(); config.MapHttpAttributeRoutes(); app.UseWebApi(config); } }
  3. 示例Web API控制器有两个公共方法: qazxsw poi

现在,当我们运行项目并将chrome指向[RoutePrefix("sample"), Authorize] public class SampleController : ApiController { [Route("public"), AllowAnonymous] public object GetPublicSample() { var message = $"Hi there, mr. {User?.Identity?.Name ?? "ANONYMOUS"}"; return new { sample = 0, message }; } [Route("protected")] public object GetProtectedSample() { var message = $"Hi there, mr. {User?.Identity?.Name ?? "ANONYMOUS"}"; return new { sample = 42, message }; } } 时,将调用此请求:

http://localhost:8080/sample/public

但是当我们去GET /sample/public HTTP/1.1 Host: localhost:8080 HTTP/1.1 200 OK Content-Length: 50 Content-Type: application/json; charset=utf-8 Server: Microsoft-HTTPAPI/2.0 Date: Wed, 28 Feb 2018 08:05:56 GMT {"sample":0,"message":"Hi there, mr. ANONYMOUS"} 时,我们有这个:

http://localhost:8080/sample/protected

除了一件事,这几乎是“预期的”。我希望当我的浏览器收到带有GET /sample/protected HTTP/1.1 Host: localhost:8080 HTTP/1.1 401 Unauthorized date: Wed, 28 Feb 2018 08:19:01 GMT www-authenticate: Negotiate,NTLM server: Microsoft-HTTPAPI/2.0 content-length: 61 content-type: application/json; charset=utf-8 {"Message":"Authorization has been denied for this request."} 头的401 HTTP响应时,他将尝试使用指定的身份验证重复相同的请求(如果请求中没有任何其他Authorization头)。但由于某种原因,他没有:(

为了使事情更有趣,我们可以看到www-authenticate实际上是AuthenticationSchemes.IntegratedWindowsAuthentication,当我删除其中一个时,事情开始按预期工作!例如:在我们的Startup类中用AuthenticationSchemes.Negotiate | AuthenticationSchemes.Ntlm替换IntegratedWindowsAuthentication并将你的brouser转到Negotiate

http://localhost:8080/sample/protected

通常,我们的服务器首先响应401 HTTP状态并设置标头GET /sample/protected HTTP/1.1 Host: localhost:8080 HTTP/1.1 200 OK date: Wed, 28 Feb 2018 08:29:55 GMT www-authenticate: tOkeN1231351234153= server: Microsoft-HTTPAPI/2.0 content-length: 59 content-type: application/json; charset=utf-8 {"sample":42,"message":"Hi there, mr. DOMAIN\\username"} ,然后使用额外的Authorization标头进行浏览器重复请求。如果我们用www-authenticate: Negotiate取代IntegratedWindowsAuthentication也一样。

还有一个例子可以让事情更加清晰。如果我们删除Ntlm并只留下AuthenticationSchemes.Anonymous,我们会注意到两件事:

  1. AuthenticationSchemes.IntegratedWindowsAuthentication端点不再可用于匿名请求(如预期的那样)
  2. /sample/public端点现在正常工作(!)

如果我们首先查看401服务器响应,我们会注意到有两个www-authenticate标头而不是一个(如前所述):

/sample/protected

所以,我的问题是:在单个GET /sample/protected HTTP/1.1 Host: localhost:8080 HTTP/1.1 401 Unauthorized Content-Length: 0 Server: Microsoft-HTTPAPI/2.0 WWW-Authenticate: Negotiate WWW-Authenticate: NTLM Date: Wed, 28 Feb 2018 08:44:04 GMT 头中放置多个身份验证方案是否“可以”?如果“是的,没关系”,为什么我的chrome没有解决这种情况呢?如果“不!这一切都错了!”,为什么www-authenticate这样做,我怎么能绕过这个?请等一下!

c# google-chrome http httplistener www-authenticate
1个回答
0
投票

这已被问过一段时间了,但我想提供我的.02。 AuthenticationSchemes.IntegratedWindowsAuthentication有点奇怪。 IWA与设置Negotiate和NTLM相同。另一方面,如果Kerberos失败,协商将回退到NTLM。 ASP.NET Core在枚举中没有IWA:HttpListener

我用:

See ASP.NET Core AuthenticationSchemes Enum
© www.soinside.com 2019 - 2024. All rights reserved.