简体   繁体   中英

OnAuthorization being called multiple times

I have a custom filter:

public class SetAuthFilter : IAuthorizationFilter
{
    public void OnAuthorization(AuthorizationContext filterContext)
    {
        //do something
    }
}

In the Application_Start() under the Global.asax :

GlobalFilters.Filters.Add(new SetAuthFilter());

The above codes will be called everytime an action is invoked.

However, in my _Layout.cshtml , I have 2 different " BaseController ", something like:

@Html.Action("SomeAction", "Base")
@Html.Action("SomeAction", "Base2")

When I set a break point, it appears that the SetAuthFilter is always being called three times, first before the page was launched, then second time when my break point hits the BaseController , then finally the third time when my break point hits the Base2Controller .

What should I do in order to avoid SetAuthFilter being called multiple times?

You simply cannot prevent it from being called if there are multiple actions that are interacting with the filter. It will be called every single request. However, you could cache your last request for that user's identity and, if it is the same request, immediately return without continuing onto the heavier authorization checks.

public class SetAuthFilter : IAuthorizationFilter
{
    public void OnAuthorization(AuthorizationContext filterContext)
    {
        var key = CreateKey(filterContext);
        var isCached = HttpRuntime.Cache.Get(key);

        if (isCached != null) return;

        HttpRuntime.Cache.Insert(key, true);
        // Heavy auth logic here
    }

    private string CreateKey(AuthorizationContext context)
    {
        // Or create some other unique key that allows you to identify 
        // the same request
        return
            context.RequestContext.HttpContext.User.Identity.Name + "|" +
            context.RequestContext.HttpContext.Request.Url.AbsoluteUri;
    }
}

Note that this doesn't account for null identities or bad URIs. You'd want to add some additional defensive checks as well as a cache invalidation strategy.

This will not allow you to bypass your authentication, since each unique request will still need to be validated. However, it minimizes the number of times you call expensive authorization logic.

For every secure controller action, the OnAuthorization overload will get called.

If you dont want that to happen, you should decorate your function with AllowAnonymous attribute.

If you don't want to call custom filter on each method: Then remove the following line from Application_Start() under the Global.asax:

GlobalFilters.Filters.Add(new SetAuthFilter());

Add [SetAuth] attribute as follows on those methods and Controllers which really needs authorization filter :

 [SetAuth]
 public ActionResult Index()
 {
    // your code
    return View(yourModel);
 }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM