好吧,这是一个很长的问题,但我认为这是值得的。我们所拥有的:
一个示例虚拟C控制台应用程序,它启动自托管的owin asp.net webapi服务(Microsoft.AspNet.WebApi.OwinSelfHostnuget包):

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();
        }
    }
}

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);
    }
}

具有两个公共方法的WebAPI控制器示例:
[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 };
    }
}

现在,当我们运行项目并将chrome指向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."}

这几乎是“如预期”,除了一件事。我希望当我的浏览器接收到401http响应时,它会尝试使用指定的身份验证重复相同的请求(如果请求中没有任何其他授权头)。但他没有,因为某些原因:(
为了使事情更有趣,我们可以看到www-authenticate实际上是AuthenticationSchemes.IntegratedWindowsAuthentication并且当我移除其中一个时,事情开始按预期工作!例如:在我们的startup类中将AuthenticationSchemes.Negotiate | AuthenticationSchemes.Ntlm替换为IntegratedWindowsAuthentication,并将brouser引导到http://localhost:8080/sample/protected
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"}

通常,我们的服务器首先响应401http状态并设置headerNegotiate,然后使用附加的授权header进行浏览器重复请求。如果我们用www-authenticate: Negotiate替换IntegratedWindowsAuthentication,也是一样的。
再举一个例子让事情更清楚。如果删除Ntlm而只保留AuthenticationSchemes.Anonymous,我们将注意到两件事:
AuthenticationSchemes.IntegratedWindowsAuthentication终结点不再可用于匿名请求(如预期的那样)
/sample/public端点现在正常工作(!)
如果我们看一下401服务器的第一个响应,我们会注意到有两个www authenticate头而不是一个(如前所述):
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

所以,我的问题是:将多个身份验证方案放在一个/sample/protected头中是否“可以”?如果“是的,没关系”,为什么我的chrome不在这种情况下呢?如果“不!完全错了!”,为什么www-authenticate要这样做,我如何绕过它?请HLP!

最佳答案

之前有人问过这个问题,但我想提供我的.02。AuthenticationSchemes.IntegratedWindowsAuthentication有点奇怪。iwa与设置negotiate和ntlm相同。另一方面,如果kerberos失败,协商将退回到ntlm。ASP.NET核心在枚举中没有iwa:See ASP.NET Core AuthenticationSchemes Enum
我使用:

listener.AuthenticationSchemes = AuthenticationSchemes.Anonymous | AuthenticationSchemes.Negotiate;

09-19 11:09