2013-05-01 126 views
7

我们有一个Web API应用程序,它提供了许多客户端可以调用和使用的Web方法。它将在IIS中进行托管并进行SSL设置。如何通过ASP.NET Web API使用Active Directory身份验证?

用户凭证存储在Active Directory中,但客户端不仅在我们的域中,它们可以位于世界任何地方,所以我的理解是我们无法使用Windows集成身份验证。

如上所述,在我们的场景中验证用户的最佳方式是什么?

我是否应该要求用户在标题中传递用户名/密码并提交每个请求?然后,我通过编程方式验证用户凭据与Active Directory的对应关系(我们已经有一个组件可以这样做),例如通过创建一个自定义的ActionFilter在每个动作执行之前运行?

另一种方法可能是创建一个HttpModule,它在每个请求之前运行,并执行身份验证,如果无效则中止请求。

我的自定义属性应该是这样的:

public class ActiveDirectoryAuthAttribute : ActionFilterAttribute 
    { 
     // todo: load from config which can change depending on deployment environment 
     private static readonly bool ShouldRequireHttps = false; 

     public override void OnActionExecuting(HttpActionContext actionContext) 
     { 
      IPrincipal principal = this.Authentiate(actionContext); 

      if (principal == null) 
      { 
       actionContext.Response = new HttpResponseMessage(HttpStatusCode.Unauthorized); 
      } 
      else 
      { 
       this.SetPrincipal(principal); 
      } 
     } 

     private IPrincipal Authentiate(HttpActionContext actionContext) 
     { 
      if (IsUriSchemaValid(actionContext.Request.RequestUri)) 
      { 
       // is the client certificate known and still valid? 
       // is IP valid? 
       // find user credentials and validate against AD 
       // create the Principle object and return it 
      } 

      return null; 
     } 

     private void SetPrincipal(IPrincipal principal) 
     { 
      Thread.CurrentPrincipal = principal; 

      if (HttpContext.Current != null) 
      { 
       HttpContext.Current.User = principal; 
      } 
     } 

     private static bool IsUriSchemaValid(Uri uri) 
     { 
      bool result = true; 

      if (ShouldRequireHttps) 
      { 
       if (!string.Equals(uri.Scheme, "https", StringComparison.InvariantCultureIgnoreCase)) 
       { 
        result = false; 
       } 
      } 

      return result; 
     } 
    } 

然后我的控制器动作里面我可以访问的主要目的:

IPrincipal principle = this.User; 

什么是认证/授权用户的最佳方式在我们的情况下,如上所述?

在上面,如何从IPrinciple创建一个对象?是否有任何现有的.NET类,或者我不得不创建我的自定义类?

回答

2

我最近一直在和AD做一个公平的比较,我想不出另一种处理这个问题的方法。

使用OAuth类型的方法可能更有意义。提供一种令牌类型路由,该路由最初将接受用户名和密码,并将自己创建并加密的令牌返回给被调用者。一旦进行了第一次初始调用,就会将令牌发回给被调用者,然后他们可以在授权头中为该调用的每个后续调用使用该令牌。

令牌对于一次呼叫或非常短的时间空间有效。每次你认为要使用的令牌时,发出另一个令牌。

您也可以考虑使用自定义OAuth实现,而不是使用数据库进行身份验证,使用AD身份存储并使用OAuth承载令牌。由于您使用的是SSL,这实际上非常适合您的情况。

相关问题