OWIN 托管的 web api:使用 windows 身份验证并允许匿名访问

Posted

技术标签:

【中文标题】OWIN 托管的 web api:使用 windows 身份验证并允许匿名访问【英文标题】:OWIN-hosted web api: using windows authentication and allow anonymous access 【发布时间】:2019-09-16 00:07:32 【问题描述】:

我有一个使用 OWIN 自托管的 WebApi 项目。

我想对控制器的某些操作启用 Windows 身份验证,但允许匿名调用其他操作。

因此,根据我在网上找到的一些示例,我在 Statrup 类中设置了这样的 WebApi:

public void Configuration(IAppBuilder appBuilder)

    HttpListener listener = (HttpListener)appBuilder.Properties["System.Net.HttpListener"];
    listener.AuthenticationSchemes = AuthenticationSchemes.IntegratedWindowsAuthentication | AuthenticationSchemes.Anonymous; //Allow both WinAuth and anonymous auth

    //setup routes and other stuff
    //...

    //Confirm configuration
    appBuilder.UseWebApi(config);

然后,在我的控制器中,我创建了两个动作:

[HttpGet]
[Authorize]
public HttpResponseMessage ProtectedAction()

    //do stuff...


[HttpGet]
[AllowAnonymous]
public HttpResponseMessage PublicAction()

    //do stuff...

但是,这不起作用。 调用标记为 AllowAnonymous 的操作按预期工作,但调用标记为 Authorize 的操作总是返回 401 错误和以下消息:


    "Message": "Authorization has been denied for this request."

即使调用方支持 Windows 身份验证,也已在浏览器(Chrome 和 Edge)和 Postman 上进行了测试。

我在这里错过了什么?

【问题讨论】:

你是如何调用 API 的?可能您的 API 客户端您没有通过 useDefaultCredentials = true。 @ManojChoudhari:正如我在问题中所说,我尝试使用 Postman(配置了 NTLM 身份验证)和与服务器在同一台机器上运行的浏览器(Chrome 和 Edge),因此它们应该自动进行身份验证默认。两者都失败了。请注意,如果我在 HttpListener 中仅启用 IntegratedWindowsAuthentication,然后不使用 Authorize/AllowAnonymous 属性,则身份验证按预期工作(使用 Postman 和浏览器)。但是,如果我这样做,我将无法将某些操作标记为已授权,而将某些操作标记为匿名,这正是我想要做的。 你是否在configure方法中使用了`appBuilder.Use(typeof(WinAuthMiddleware));`? @ManojChoudhari:什么是 WinAuthMiddleware 类,我在哪里可以找到它?它是 nuget 包的一部分吗? 还有一件事 - 您是否在 IIS / IIS Express 中托管此 Web API?您是否检查了 IIS 设置中是否同时启用了 Windows/匿名身份验证。 【参考方案1】:

由于您对问题的描述有点有限,我设置了一个演示应用程序,其中我将OAuthAuthorizationServerProvider 实现为OAuthAuthorizationServerOptions 的提供者并覆盖GrantResourceOwnerCredentialsValidateClientAuthentication

  public void Configuration(IAppBuilder app)
    
        app.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions
        
            Provider = new ApplicationOAuthBearerAuthenticationProvider()
        );
        app.Use<AuthenticationResponseMiddleware>();
        var options = new OAuthAuthorizationServerOptions
        
            AllowInsecureHttp = true,
            TokenEndpointPath = new PathString("/api/xxxx"),
            AccessTokenExpireTimeSpan = TimeSpan.FromDays(1), 
            Provider = new OwinAuthorisationProvider()

        ;
        app.UseOAuthAuthorizationServer(options);

    

还尝试了自定义AuthorizeAttribute并在配置类.Filters.Add(new AuthorizeAttribute());中添加为过滤器

AuthenticationResponseMiddleware 我继承OwinMiddlewarepublic override async Task Invoke(IOwinContext context) 方法请检查请求的流程。

它首先在RequestToken 方法中点击OAuthBearerAuthenticationProvider,然后到OwinMiddleware 类,然后再转到任何DelegatingHandler 管道, 大多数情况下,您的身份验证都是在这一层实现的。

请在此检查后评论您的发现,同时我也修改了 API 并更新了您,希望对您有所帮助。

【讨论】:

感谢您的回答,但看起来(如果我错了,请纠正我)您建议使用 OAuth。相反,我想使用的是 Windows 身份验证 (NTLM/Kerberos)。两者兼容吗?我可以使用 OAuth 进行 Windows 身份验证吗?浏览器将如何处理这个问题,它会像 NTLM 那样向用户显示用户名/密码提示吗?抱歉,可能是愚蠢的问题,但我不熟悉 OAuth。 是的,你是对的,我正在使用 OAuth 进行演示。我给出的示例是使用 Oauth,如果您愿意,我可以开发基于 OAuth 令牌的身份验证。请在此处参考带有 Windows 身份验证的 OAuth,docs.wso2.com/display/AM210/Kerberos+OAuth2+Grant 我对 Windows OAuth 身份验证的了解有限,因此可能需要一些时间。【参考方案2】:

好吧,我在另一个问题中找到了解决方法。 您可以在运行时为每个请求选择身份验证模式,而不是指定多个身份验证模式(这不起作用),方法是设置如下 AuthenticationSchemeSelector 方法:

public void Configuration(IAppBuilder app)

    HttpListener listener = (HttpListener)appBuilder.Properties["System.Net.HttpListener"];
            listener.AuthenticationSchemeSelectorDelegate = new 
    AuthenticationSchemeSelector(GetAuthenticationScheme);


private AuthenticationSchemes GetAuthenticationScheme(HttpListenerRequest httpRequest)

    if(/* some logic... */)
        return AuthenticationSchemes.Anonymous;                    
    
    else
        return AuthenticationSchemes.IntegratedWindowsAuthentication;
    

虽然不理想(您必须手动检查请求 URL 或请求的其他一些参数来决定使用哪种方法)。

【讨论】:

以上是关于OWIN 托管的 web api:使用 windows 身份验证并允许匿名访问的主要内容,如果未能解决你的问题,请参考以下文章

在 DELETE 上不允许使用 Owin 自托管 Web API 405 方法

在使用 Owin 自托管的 Web API 中获取远程主机 IP

asp.net web api 自托管 / owin / katana

具有 OWIN 自托管的 Web API 无类型 OData 服务返回 406 Not Acceptable

支持 https 的 Owin 自托管控制台应用程序(无 Web api,无 SignalR)

具有 OWIN 自主机和 Windows 身份验证的 Web Api