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

时间:2013-07-02 18:36:03

标签: authentication asp.net-web-api authorization

情况

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

我在网上看到了各种人们使用[Authorize]属性进行安全性的示例。我认为这是通过网页上的AJAX调用Web API的时候。

我还看到了各种示例,其中API密钥与每个请求一起传递(通过查询字符串或标头)。我认为这是从外部系统调用Web API的时候。

问题

以下是立即浮现的问题:

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

附注

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

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

2 个答案:

答案 0 :(得分:4)

[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;
    }
    ...
}

正如您所看到的,它只是获取Thread.CurrentPrincipal并检查身份是否经过身份验证。当然,当您包含角色时,还有其他检查。

因此,这意味着只要Thread.CurrentPrincipal作为身份验证的结果,您就可以使用不同的身份验证方法。如果您有两个处理程序(如果是Web主机,则为HttpModules)或Web API 2中的身份验证过滤器,您可以根据不同的因素建立身份。例如,您可以将BasicAuthnHandlerApiKeyHandler添加到config.Handlers,从而依次在Web API管道中运行。他们可以做的是查找凭据并设置Thread.CurrentPrincipal。如果基本方案中包含Authorize标头,则BasicAuthnHandler将进行身份验证并设置Thread.CurrentPrincipal,如果API密钥进入,则不执行任何操作,ApiKeyHandler设置Thread.CurrentPrincipal 。两个处理程序都可以创建相同类型的主要说法GenericPrinicpal或甚至不同的。这并不重要,因为所有主体都必须实现IPrincipal。因此,在Authorize过滤器运行时,Thread.CurrentPrincipal将被设置,无论您如何进行身份验证,授权都将起作用。注意:如果您是网络托管服务商,除了HttpContext.User之外,您还需要设置Thread.CurrentPrincipal

答案 1 :(得分:2)