MVC 5.0 [AllowAnonymous] and the new IAuthenticationFilter

放肆的年华 提交于 2019-11-30 17:20:46

In regards to : Question 1) I was under the impression that the [AllowAnonymous] attribute would automagically bypass any code within my CustomAuthenticationAttribute but I was wrong! Do I need to manually check for the existence of the [AllowAnonymous] attribute and skip any code?

As far as I know [AllowAnonymous] attribute has nothing to do with a CustomAuthenticationAttribute. They have different purposes. [AllowAnonymous] would have an effect during an Authorization context, but not in Authentication context.

The Authentication filter has been implemented for setting up authentication context. For instance, AuthenticationContext provides you information for performing authentication. You can use this information to make authentication decisions based on the current context. For example, you may decide to modify the ActionResult to different result type based on the authentication context, or you may decide to change the current principal based on the authentication context etc.

OnAuthenticationChallenge method runs after the OnAuthentication method. You can use OnAuthenticationChallenge method to perform additional tasks on the request.

In regards to : Question 2) Why is the code inside my Index() method of my HomeController gets executed after the OnAuthentication? Only to realize that after I return View() do the code inside the OnAuthenticationChallenge() gets executed?

This is the expected behaviour. Since the you have a Globally registered Authentication filter, the very first thing is that, before any action executes, it would first fire the OnAuthentication event as you would have noticed. Then the OnAuthenticationChallenge after the Index being executed. Once the Action is succeeded any authentication filter relevant that Action (i.e Index), would run the OnAuthenticationChallenge so it can contribute to the action result. As you have in your code for OnAuthenticationChallenge you can modify the ActionResult to an HttpUnauthorizedResult this would get negotiated with the ActionResult.

In answer to Question 1:

The [AllowAnnoymous] attribute acts like a flag (it actually has no implementation logic within it). Its presence is merely checked for by the [Authorize] attribute during execution of OnAuthorization. Decompiling the [Authorize] attribute reveals the logic:

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

        if (skipAuthorization)
        {
            return;
        }

[AllowAnnonymous] would never 'automagically' bypass the code in your custom attribute...

So the answer to the second half of Question 1 is: Yes - if you want your custom attribute to react to the presence of the [AllowAnnonymous], then you would need to implement a check (similar to the above) for the [AllowAnnonymous] attribute in your custom [Authorize] attribute.

I need to provide a clarification here to your second question:

Question 2) Why is the code inside my Index() method of my HomeController gets executed after the OnAuthentication? Only to realize that after I return View() do the code inside the OnAuthenticationChallenge() gets executed?

You should actually be testing for credentials in OnAuthentication if you want to prevent the user from executing the code in your action method. OnAuthenticationChallenge is your chance to handle the 401 with a custom result, such as redirecting the user to a custom controller/action and give them a chance to authenticate.

public class CustomAuthenticationAttribute : ActionFilterAttribute, IAuthenticationFilter 
{
    public void OnAuthentication(AuthenticationContext filterContext)
    {
            var user = filterContext.HttpContext.User;
        if (user == null || !user.Identity.IsAuthenticated)
        {
            filterContext.Result = new HttpUnauthorizedResult();
        }
    }

    public void OnAuthenticationChallenge(AuthenticationChallengeContext filterContext)
    {
        // modify filterContext.Result to go somewhere special...if you do
        // nothing here they will just go to the site's default login
    }
}

Here is a more complete run-through of the filter and how you might work with it: http://jameschambers.com/2013/11/working-with-iauthenticationfilter-in-the-mvc-5-framework/

Cheers.

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!