我应该在ActionFilter中测试AdalException吗?

时间:2017-07-17 18:41:32

标签: azure-active-directory adal action-filter

在GitHub like this one上的一些Azure示例中,我们有一个使用ADAL访问受保护的Web API资源的示例。该尝试受try / catch查找AdalException

的保护

我将这样总结代码:

 try 
 { 
     //pseudo code...  configure a client to use an access token..
     var token = ADAL.AcquireTokenAsync...
     var httpClient = new HttpClient(baseUri, token);

     // use the token for querying some protected API
     var result = //await HttpClient to return data...

     return View(result); 
 } 
 catch (AdalException) 
 { 
     // do something important with the exception, 
     // e.g. return an error View w/login link
 } 

因此,当我开始充实我的MVC控制器以使用ADAL-access_token'd请求时,我是否真的希望在每个控制器中都进行所有这些try / catch业务?

创建ActionFilter是否有意义?这个片段的灵感来自我在this Azure Sample

看到的代码
public class AdalErrorAttribute : FilterAttribute, IExceptionFilter
{
    void IExceptionFilter.OnException(ExceptionContext filterContext)
    {
        if(filterContext.Exception is AdalException)
        {
            if (filterContext.RequestContext.HttpContext.Request.QueryString["reauth"] == "True")
            {
                //
                // Send an OpenID Connect sign-in request to get a new set of tokens.
                // If the user still has a valid session with Azure AD, they will not be prompted for their credentials.
                // The OpenID Connect middleware will return to this controller after the sign-in response has been handled.
                //
                filterContext.RequestContext.HttpContext.GetOwinContext().Authentication.Challenge(
                    new AuthenticationProperties(),
                    OpenIdConnectAuthenticationDefaults.AuthenticationType);
            }
        }
    }
}

我的上下文: 我正在使用一组相当同质的支架MVC控制器,它们在生成时以EntityFramework为中心。但现在需要重新加工以访问我的Web API(通过我的新AutoRest客户端)

2 个答案:

答案 0 :(得分:2)

该方法存在两个问题。

  1. 您提及的示例代码和过滤器实现适用于Web APP,而不是Web API。这是一个重要的区别。 Web APP可以依靠浏览器与用户进行交互以进行身份​​验证;网络API不知道客户端有什么用户体验(或者甚至根本没有任何用户体验),因此错误行为完全不同
  2. 控制器可能会调用多个API,需要针对不同资源的多个令牌请求 - 这些请求可能会失败或独立成功,并连接到不同的提供者。不同的控制器可能会调用不同的对错误的反应可能会有所不同。像你原型那样的过滤器只能帮助一组非常狭窄的案例。 因此,我会说除非你的控制器都需要执行非常均匀的逻辑,否则上面的过滤器不会给你所需的灵活性。

答案 1 :(得分:2)

@vibronet提出了一个很好的观点 - 为您的WebAPI端点做到这一点。他们使用bearer auth进行调用,并且不应自动重定向到登录过程。返回401表示凭据无效并让它继续。

但是对于一个MVC应用程序,用户正在以交互方式使用,这是一个合理的想法,受到一些限制。

  1. 确保您的过滤器与其匹配的内容非常紧密。 IE浏览器。确保它处理异常,你可以合理地 - 肯定会引发认证问题(相对于访问被拒绝的问题)。也许是由您的包装逻辑抛出的自定义异常,或超出它的一些额外条件是ADALException,以确保通过再次登录可以解决该问题。
  2. 除非您确实希望每个请求都有此处理,否则请查看将其附加到控制器或操作层而不是全局。
  3. 留意潜力"循环"问题,你得到一个错误,告诉用户再次登录,获取错误,让他们再次登录等。也许在触发登录时,或在登录过程中,或者类似的东西,在会话中设置一些数据。最好提供错误消息,而不是让用户的浏览器陷入无限重定向循环。 (当然,这也适用于手动处理异常情况)
  4. 希望有所帮助。