如何使ASP.NET Web API适当地响应403或401?

时间:2013-03-31 20:50:42

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

我正在使用ASP.NET Web API。我确实喜欢添加属性来指定API控制器的访问级别,如下所示:

[Authorize]
public IEnumerable<Activity> Get()

到目前为止一直很好,但是当我使用角色时,这个概念就分崩离析了。

[Authorize(Roles = "Manager")]
public IEnumerable<Activity> Get()

我的用户可能在一段时间后登录系统,然后在某些时候他们点击了一个“禁止”他们的资源。尝试再次登录的用户没有任何意义。由于他们的合法帐户无权访问该URL。但目前他们获得401(未经授权)而不是403(被禁止),就像他们使用错误的帐户登录一样。但是,用户只有一个帐户,用户不会要求拥有属于其他人的帐户。

还有其他人处理过这个问题吗?有谁知道如何解决这一问题?我非常愿意编写代码来解决这个问题,但我目前无法从哪里开始。

3 个答案:

答案 0 :(得分:29)

阅读Parv的建议,我创建了以下自定义过滤器,名为 [WebApiAuthorize]

关键是HandleUnauthorizedRequest()方法。当代码在此方法中执行时,这是因为用户未经授权&#34;由于某种原因&#34; ....所以现在我们只是确定&#34;为什么&#34; ....然后要么:

  1. 默认行为的调用基本方法(返回401)....或....
  2. 使用403返回我们自己的回复。
  3. 如您所见,它在适当时返回403(经过身份验证,但未经授权)。

    [WebApiAuthorize(Roles = "YourRoleA,YourRoleB")]
    public class AdminController : ApiController
    {
        public List<Admin> GetAdmins()
        {
            ...
        }
    } 
    

    要使用,只需将自定义过滤器抛出控制器或此类动作.....

    {{1}}

答案 1 :(得分:1)

我做了一些研究,我为我编写了一个解决方案。我在System.Web.Mvc上找到了两个不同的Authorize属性,在System.Web.Http中找到了第二个。第一个应用于常规MVC4应用程序,第二个应用于MVC4的WebAPI部分,用于Web服务,包括RESTful接口。所以我使用了第二个。

我决定查看codeplex上的Authorize Attribute Source代码。我发现了这个:

    protected virtual bool IsAuthorized(HttpActionContext actionContext)
    {
        if (actionContext == null)
        {
            throw Error.ArgumentNull("actionContext");
        }

        IPrincipal user = Thread.CurrentPrincipal;
        if (user == null || !user.Identity.IsAuthenticated)
        {
            return false;
        }

        if (_usersSplit.Length > 0 && !_usersSplit.Contains(user.Identity.Name, StringComparer.OrdinalIgnoreCase))
        {
            return false;
        }

        if (_rolesSplit.Length > 0 && !_rolesSplit.Any(user.IsInRole))
        {
            return false;
        }

        return true;
    }

很容易看出认证和访问是如何混合的,因为它们都具有返回false的相同效果。

这是我写的new AuthorizeAttribute,当用户或角色不匹配时返回403。这样您就可以避免在本地登录窗口。它包括以下代码。

        if (!IsAuthorized(actionContext))
        {
            HandleUnauthorizedRequest(actionContext);
        }

        if (!IsAllowed(actionContext))
        {
            HandleForbiddenRequest(actionContext);
        }

答案 2 :(得分:0)

你可以做的是做一个自定义Authorize attribute,然后处理 AuthorizeCoreOnAuthorizationFailed在后​​一种情况下,您可以发送您提供的任何回复

有一个look here