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
的提供者并覆盖GrantResourceOwnerCredentials
和ValidateClientAuthentication
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
我继承OwinMiddleware
和public 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