MVC Source Analysis - Authorize Authorization Filter

Keywords: ASP.NET Attribute Session

from Last article As you can see, there are four kinds of filters for program execution:

Type of filter

Interface

describe

Authorization

IAuthorizationFilter

This type (or filter) is used to restrict access to a controller or a behavioral method of the controller.

Exception

IExceptionFilter

Used to specify an action that handles exceptions thrown in a behavior method or controller

Action

IActionFilter

Processing before or after entry

Result

IResultFilter

Processing before or after the result is returned

 

But there are only three filters that implement them by default: Authorize, ActionFilter and HandleError; the various information is shown in the table below.

Filter

Class name

Implementation interface

describe

ActionFilter

AuthorizeAttribute

IAuthorizationFilter

This type (or filter) is used to restrict access to a controller or a behavioral method of the controller.

HandleError

HandleErrorAttribute

IExceptionFilter

Used to specify an action that handles exceptions thrown in a behavior method or controller

custom

ActionFilterAttribute

IActionFilter and IResultFilter

Processing before or after entering an action or before or after returning a result

 

Now let's introduce these filters.

 

Authorize filter

1. Mode 1: OnAuthorization method in Controller class

In our new controller class, we will inherit directly or indirectly from the Controller class, so in Controller, there is an OnAuthorization method, which is also in the authorization filter.

// abstract: 
//     Define the methods required for authorization filters.
public interface IAuthorizationFilter
{
    // abstract: 
    //     Called when authorization is required.
    //
    // parameter: 
    //   filterContext:
    //     Filter context.
    void OnAuthorization(AuthorizationContext filterContext);
}

This way, you don't need to configure your own filters in the FilterConfig file.

I'll build a feature first, so long as the method adds this feature, it doesn't need login validation.

public class AllowLoginAttribute : Attribute
{
}

There is nothing in it and nothing is needed.

Then there's the filter method.

public class HomeController : Controller
{
    protected override void OnAuthorization(AuthorizationContext filterContext)
    {
        var attrs = filterContext.ActionDescriptor.GetCustomAttributes(typeof(AllowLoginAttribute), true);
        if (attrs.Count() > 0)
        {
            return;
        }
        var cookie = Request.Cookies["Login"];
        if (cookie == null || cookie.Value != "Already Login")
        {
        //As explained earlier, just assigning Result can affect the flow of MVC. filterContext.Result
= RedirectToAction("Login"); } }   
   //This method gives the browser a Cookie to identify whether it is logged in or not.
   //In practice, it can be used as a login page to request login, and then to Cookie and Session.
[AllowLogin]
public ActionResult Login() { HttpCookie cookie = new HttpCookie("Login", "Already Login"); cookie.Expires = DateTime.Now.AddMinutes(3); Response.Cookies.Add(cookie); return View(); }   
   //Here is the page I want to visit.
public ActionResult Index() { return View(); } }

Next, I'll go directly to the Index page to see:

Jump to the landing page directly, at this time, the browser has got the desired Cookie, then go to the Index page to see.

Successful visit.

Since this method is written in the controller, it is only valid for the method in the controller. That is to say, if I visit another controller at this time, this method will not work.

So, am I going to write it once in each controller? Or am I going to make a parent class of the controller myself and let other classes inherit the classes I wrote? Is that a bit too much trouble?

What about swelling? The method is right below.

 

2. Mode 2: On Authorization Method of AuthorizeAttribute

The contents of the method are the same as those above, but the location of the method is different.

But there are several differences.

2.1 You need to register your own filters in FilterConfig

public class FilterConfig
{
    public static void RegisterGlobalFilters(GlobalFilterCollection filters)
    {
        filters.Add(new MyAuthAttribute());
        filters.Add(new HandleErrorAttribute());
    }
}

2.2 When you jump, it's slightly different.

public class MyAuthAttribute : AuthorizeAttribute
{public override void OnAuthorization(AuthorizationContext filterContext)
    {
        var attrs = filterContext.ActionDescriptor.GetCustomAttributes(typeof(AllowLoginAttribute), true);
        if (attrs.Count() > 0)
        {
            return;
        }
        var cookie = HttpContext.Current.Request.Cookies["Login"];
        if (cookie == null || cookie.Value != "Already Login")
        {
            filterContext.Result = new RedirectToRouteResult(
          new RouteValueDictionary(new { controller = "Home", action = "Login" })); return; } } }

2.3 It's better to modify the configuration in the Web.config file.

<system.web>
    <authentication mode="Forms">
      <forms loginUrl="~/Home/Login" timeout="2880" />
    </authentication>
</system.web>

I've tested myself. It's OK. The result is not posted. I can't see anything else. It's the same as above.

 

3. Mode 3: AuthorizeAttribute's AuthorizeCore method

This method is simple, as long as it returns false, it will jump back according to the configuration file configuration above. Usually the OnAuthorization and AuthorizeCore methods here are used together.

Take a look at the code:

public class MyAuthAttribute : AuthorizeAttribute
{
   //In this method, I determine whether the user has logged in or not. protected override bool AuthorizeCore(HttpContextBase httpContext) { bool isAuth = httpContext.User.Identity.IsAuthenticated; return isAuth; }        
   //In this method, I determine whether an Action needs to log in. public override void OnAuthorization(AuthorizationContext filterContext) { var attrs = filterContext.ActionDescriptor.GetCustomAttributes(typeof(AllowLoginAttribute), true); if (attrs.Count() > 0) { return; } base.OnAuthorization(filterContext); } }

Then you need to modify the Login method in the HomeController controller.

[AllowLogin]
public ActionResult Login()
{
   //After executing this method, Identity can get true there FormsAuthentication.SetAuthCookie("Login", false); return View(); }

If you do not want to modify the configuration file and want to complete a custom jump in the program, you can override the AndleUnauthorized Request method of AuthorizeAttribute, such as:

protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
{
    filterContext.HttpContext.Response.Redirect("~/Home/Login");
}

This method deals with things that do not pass permission validation.

There are also two ways to use this filter.

1. You can register in the FilterConfig file as above, so you can walk through the filter once.

2) There's another way, more flexible. It's not registered. It's just adding features to methods that want to validate permissions. Other methods are not affected.

[MyAuth]
public ActionResult Index()
{
    return View();
}

This method will only be validated here, because I marked the method that needs to be validated. For other methods, it will not be validated. It is very flexible.

Directory synchronized

Posted by gusaps on Wed, 20 Mar 2019 15:09:29 -0700