3

I want to write a custom filter which will check whether a user is logged in to my site, and redirect them back to the login page if they aren't.

I want the filter to apply automatically to the page when it loads.

I have tried the solution shown below, but the filter doesn't work at the moment.

Filter Code:

using Microsoft.AspNetCore.Mvc.Filters;

namespace MODS.Filters
{
    public class AuthorisationPageFilter : ActionFilterAttribute
    {
        public override void OnActionExecuted(ActionExecutedContext context)
        {
            System.Diagnostics.Debug.Write("Filter Executed");  //write to debugger to test if working

            //add real code here

            base.OnActionExecuted(context);
        }
    }
}

Next, here's the filter attribute applied to the page model:

using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using MODS.Filters;

namespace MODS.Pages.Menus
{
    [AuthorisationPageFilter]
    public class Admin_MainMenuModel : PageModel
    {
        public ActionResult Admin_MainMenu()
        {
            System.Diagnostics.Debug.Write("Function Executed");
            return new ViewResult();
        }
    }
}

I am under the impression that you need to call an action/method on the page for the function to apply when the page loads (please tell me if this is correct), so here is the code calling the Admin_MainMenu method in the .cshtml page file (in a code block at the top of the razor page):

Model.Admin_MainMenu();

My current thoughts are that either: 1. the filter itself is of the wrong type (could be IPageFilter instead?) 2. that the way I'm implementing it is wrong (either where I apply it to the page model, or when I call the method on the page).

Any help is greatly appreciated. Thanks.

Tetsuya Yamamoto
  • 21,982
  • 5
  • 34
  • 53
bbbb
  • 189
  • 2
  • 12
  • Are you using Identity to manage authentication? If so, you can just put `[Authorize]` on your PageModel. If not, how are you authenticating users? – Mike Brind Dec 01 '18 at 09:08

2 Answers2

2

ActionFilterAttribute is for MVC (Controllers and Actions). For Razor Pages, you must use IPageFilter (IAsyncPageFilter for async implementation).

There are two different filter pipelines for MVC and Razor Pages

Razor Page filters IPageFilter and IAsyncPageFilter allow Razor Pages to run code before and after a Razor Page handler is run. Razor Page filters are similar to ASP.NET Core MVC action filters, except they can't be applied to individual page handler methods.

Filter methods for Razor Pages in ASP.NET Core

helvete
  • 1,416
  • 5
  • 26
  • 26
0

This answer is for AspNet MVC rather than AspNetCore MVC, but may be useful to someone:

If it's for Authorization, I would use the AuthorizeAttribute class.

Something like this:

using System.Web.Mvc;

namespace MODS.Filters
{
    public class CustomAuthorizeUserAttribute : AuthorizeAttribute
    {
        // Custom property, such as Admin|User|Anon
        public string AccessLevel { get; set; }

        // Check to see it the user is authorized
        protected override bool AuthorizeCore(HttpContextBase httpContext)
        {
            System.Diagnostics.Debug.Write("Authorize Executed");  //write to debugger to test if working

            // Use Core MVC Security Model
            var isAuthorized = base.AuthorizeCore(httpContext);
            if (!isAuthorized)
            {
                return false;
            }

            // Or use your own method of checking that the user is logged in and authorized. Returns a Boolean value.
            return MySecurityHelper.CheckAccessLevel(AccessLevel);
        }

        // What to do when not authorized
        protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
        {
            filterContext.Result = new RedirectToRouteResult(
                    new RouteValueDictionary(
                        new
                        {
                            controller = "Error",
                            action = "NotFound"
                        })
                    );
        }
    }
}

Then Decorate the Controller or Action with the CustomAuthorizeUser Attribute:

using MODS.Filters;

namespace MODS.Pages.Menus
{
    [CustomAuthorizeUser(AccessLevel = "Admin")]
    public class Admin_MainMenuModel : PageModel
    {
        public ActionResult Admin_MainMenu()
        {
            System.Diagnostics.Debug.Write("Function Executed");
            return new ViewResult();
        }
    }
}

Hope this helps!

Matt D
  • 2,764
  • 1
  • 10
  • 24
  • Thanks for your answer. Unfortunately, it seems that the `: AuthorizeAttribute` class is only available in ASP.NET MVC, and not ASP.NET Core, which is what I'm using. My main issue here is how to implement an `: ActionFilterAttribute` (or some more suitable .NET core equivalent) so that the filter is used every time the page is done loading. – bbbb Nov 29 '18 at 13:45
  • Ok, I didn't realise that. I found this question, which has some good answers that may help: https://stackoverflow.com/questions/31464359/how-do-you-create-a-custom-authorizeattribute-in-asp-net-core – Matt D Nov 29 '18 at 13:53
  • Thanks, I think that post will be useful. As a side question, I was wondering if a filter is really the best way to do this kind of redirection. I'm quite new to ASP.NET, and was wondering if you (or indeed anyone) else had an opinion on this matter. – bbbb Nov 29 '18 at 14:19