5

I'm trying to set default access to the methods on my controller, so I've added the [Authorize] attribute on my ApiController.

For the most part, unless overridden with the [AllowAnonymous] attribute this works fine.

Now I want to add another level into the mix. For my authorized methods by default, I want them to require a specific role (such as admin) so I updated the controller level attribute to [Authorize(roles="admin")]. For a few exceptions, I don't care what role they are (just being authenticated is good enough).

I thought I could stick with setting the Authorize attribute at the controller level and override it at the individual method level, but this doesn't appear to work the same way as [AllowAnonymous] does.

Are there any suggestions out there on how to go about this without having to remember to decorate every new method with the default access level? Something like [Authorize(roles="*")]? Even if I needed to have a default role that every user was a part of like AuthenticatedUsers, that would be fine.

4

2 回答 2

8

如何创建标记属性?AllowAnonymous 就是这样一个标记,顺便说一句。当标记存在时,创建您自己的 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);
    }
}
于 2013-05-08T15:30:26.317 回答
2

这基本上就是我正在做的事情。我创建了一个自定义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;
    }
}
于 2013-05-08T05:38:22.377 回答