Fred
Fred

Reputation: 3421

When apply an attribute in class and method together, How to force use method attribute?

I have an attribute to check authentication in controller actions. My attribute like this :

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true, Inherited = true)]
public class AuthenticationRequiredAttribute : ActionFilterAttribute, IAuthenticationFilter
{
    private readonly bool checkAuthentication;
    public AuthenticationRequiredAttribute(bool checkAuthentication)
    {
        this.checkAuthentication = checkAuthentication;
    }

    public void OnAuthentication(AuthenticationContext filterContext)
    {
        if (checkAuthentication && !UserIdentity.IsAuthenticated)
            filterContext.Result = new HttpUnauthorizedResult(); 
    }

    public void OnAuthenticationChallenge(AuthenticationChallengeContext filterContext)
    {
        if (filterContext.Result == null || filterContext.Result is HttpUnauthorizedResult)
        {
            filterContext.Result = new RedirectToRouteResult(
                        new System.Web.Routing.RouteValueDictionary{
                                        {"controller", "Account"},
                                        {"action", "Login"}
                                    });
        }
    }
}

If checkAuthentication = false no check authentication. All actions in a controller should be check authentication except one action. I apply [AuthenticationRequired(true)] on controller and [AuthenticationRequired(false)] on specific action. but it not work and always check authentication. When apply [AuthenticationRequired(true)] on other actions and remove it from controller it work fine.

How I can force use method attribute in this case?

Upvotes: 1

Views: 2011

Answers (2)

Mark Twain
Mark Twain

Reputation: 836

Modify your OnAuthentication and add validation of AllowAnonymous attribute.

bool skipAuthorization = filterContext.ActionDescriptor.IsDefined(typeof(AllowAnonymousAttribute), inherit: true)
                                 || filterContext.ActionDescriptor.ControllerDescriptor.IsDefined(typeof(AllowAnonymousAttribute), inherit: true);

        if (skipAuthorization)
        {
            return;
        }

After that just add AllowAnonymous attribute to methods that should skip authentication\authorization.

Upvotes: 3

JB06
JB06

Reputation: 1931

If you apply a controller level filter, then it applies to all actions and overrides any filters of the same name.

You can either just apply the filter to each action, or try using the accepted answer here. This will let you specify what actions to exclude.

Upvotes: 1

Related Questions