控制器级别的默认授权角色,并在方法时覆盖

时间:2013-05-07 23:19:38

标签: c# asp.net-mvc controller asp.net-web-api authorization

我正在尝试设置控制器上方法的默认访问权限,因此我在[Authorize]上添加了ApiController属性。

在大多数情况下,除非被[AllowAnonymous]属性覆盖,否则这样可以正常工作。

现在我想在混音中添加另一个级别。对于默认情况下我的授权方法,我希望它们需要特定的角色(例如admin),因此我将控制器级别属性更新为[Authorize(roles="admin")]。除了少数例外,我不关心它们是什么角色(只是经过身份验证就足够了)。

我认为我可以坚持在控制器级别设置Authorize属性并在单个方法级别覆盖它,但这似乎与[AllowAnonymous]的工作方式不同。

有没有关于如何解决这个问题的建议,而不必记得用默认访问级别装饰每个新方法?像[Authorize(roles="*")]这样的东西?即使我需要一个默认角色每个用户都是 AuthenticatedUsers 的一部分,那也没关系。

2 个答案:

答案 0 :(得分:8)

如何创建标记属性? AllowAnonymous是一个这样的标记,BTW。当标记在那里时,创建您自己的Authorize属性并清除角色。

[MyAuth(Roles = "admin")]
public class ValuesController : ApiController
{
    [ExemptRoles]
    public IEnumerable<string> Get()
    {
        return new string[] { "value1", "value2" };
    }
}

public class ExemptRolesAttribute : Attribute { }

public class MyAuthAttribute : AuthorizeAttribute
{
    public override void OnAuthorization(System.Web.Http.Controllers.HttpActionContext actionContext)
    {
        if (actionContext.ActionDescriptor.GetCustomAttributes<ExemptRolesAttribute>().Any())
            base.Roles = String.Empty;

        base.OnAuthorization(actionContext);
    }
}

答案 1 :(得分:1)

这基本上就是我正在做的事情。我创建了自定义AuthorizeAttribute并覆盖了OnAuthorization方法。

然后,我可以检查用户是否是当前自定义属性中标记的任何角色 如果没有,我将回归默认授权处理。

public class InternalAuthorizeAttribute : AuthorizeAttribute
{
    public override void OnAuthorization(System.Web.Http.Controllers.HttpActionContext actionContext)
    {
        if(actionContext == null)
            throw new ArgumentNullException("actionContext");
        if (AuthorizeRequest(actionContext))
            return;

        // no special authorization found. fall back to base (handles AllowAnonymous, and Controller level attribute)
        base.OnAuthorization(actionContext);
    }


    private bool AuthorizeRequest(HttpActionContext actionContext)
    {
        if (!actionContext.ActionDescriptor.GetCustomAttributes<InternalAuthorizeAttribute>().Any())
            return false;

        foreach (AuthorizeAttribute attribute in actionContext.ActionDescriptor.GetCustomAttributes<AuthorizeAttribute>())
        {
            foreach (var role in attribute.Roles.Split(','))
            {
                if (HttpContext.Current.User.IsInRole(role)) return true;
            }
        }
        return false;
    }
}