同一 ASP.NET Web API 的不同身份验证方案

Tra*_*rks 2 authentication authorization asp.net-web-api

情况

我有一个即将进行的项目,其中网页将进行 AJAX 调用。还将向外部客户端提供 REST API。我将使用 ASP.NET MVC 4 和 Web API 来实现这个项目。

我在网上看到了人们使用该[Authorize]属性来确保安全的各种示例。我认为每当在网页上通过 AJAX 调用 Web API 时就会发生这种情况。

我还看到过各种示例,其中 API 密钥随每个请求一起传递(通过查询字符串或标头)。我认为每当从外部系统调用 Web API 时就会发生这种情况。

问题

以下是我立即想到的问题:

  • 我应该为内部和外部客户端创建单独的控制器吗?
  • 或者我应该强制网页使用相同的外部身份验证模型?
  • 或者有没有一种方法可以让外部客户端使用授权属性?
  • 或者我应该以某种方式同时支持两种表单或身份验证?

旁注

一位同事指出,我可能希望将 API 部署到与托管 Web 应用程序的位置完全不同的 URL。同样,他指出外部 API 可能需要更粗粒度或单独发展。

我不想在这里重新发明轮子。这让我想知道我是否应该首先使用 Web API 作为 AJAX 调用的内部 API,或者是否应该坚持使用带有属性的老式 MVC 操作[HttpPost]

Bad*_*dri 5

[Authorize]属性不仅仅适用于 Ajax。当您应用该[Authorize]属性来表示操作方法时,它的作用是确保在操作方法运行之前对身份进行身份验证,无论客户端发出请求,也无论提交给 API 的凭据类型如何。它所寻找的只是Thread.CurrentPrincipal. 这是过滤器中代码的复制粘贴Authorize

protected virtual bool IsAuthorized(HttpActionContext actionContext)
{
    ...
    IPrincipal user = Thread.CurrentPrincipal;
    if (user == null || !user.Identity.IsAuthenticated)
    {
        return false;
    }
    ...
}
Run Code Online (Sandbox Code Playgroud)

正如您所看到的,它所做的一切都是获取Thread.CurrentPrincipal并检查身份是否经过身份验证。当然,当您包含角色时,还会进行额外的检查。

Thread.CurrentPrincipal因此,这意味着只要设置为身份验证结果,您就可以使用不同的身份验证方式。如果您有两个处理程序(或HttpModules在 Web 托管的情况下)或身份验证过滤器(在 Web API 2 的情况下),您可以根据不同因素建立身份。例如,您可以将 aBasicAuthnHandler和 aApiKeyHandler添加到config.HandlersWeb API 管道中,从而在 Web API 管道中依次运行。他们能做的就是寻找凭证并进行设置Thread.CurrentPrincipal。如果Authorizeheader 出现在基本方案中,BasicAuthnHandler则会进行身份验证并设置Thread.CurrentPrincipal,如果 API 密钥出现,则不会执行任何操作并ApiKeyHandler设置Thread.CurrentPrincipal。两个处理程序都可以创建相同类型的主体GenericPrinicpal,甚至不同的主体。没关系,因为所有的校长都必须执行IPrincipal。因此,当Authorize过滤器运行时,Thread.CurrentPrincipal将被设置并且无论您如何进行身份验证,授权都将起作用。注意:如果您是虚拟主机HttpContext.User,除了Thread.CurrentPrincipal.