4

So my project requirements changed and now I think I need to build my own action filter.

So, this is my current login controller:

 public class LoginController : Controller
{
    // GET: Login
    public ActionResult Index()
    {
        return View();
    }

    [HttpPost]
    [AllowAnonymous]
    [ValidateAntiForgeryToken]

    public ActionResult Login(LoginViewModel model)
    {  
        string userName = AuthenticateUser(model.UserName, model.Password);
        if (!(String.IsNullOrEmpty(userName)))
        {
            Session["UserName"] = userName;
            return View("~/Views/Home/Default.cshtml");
        }

        else
        {
            ModelState.AddModelError("", "Invalid Login");
            return View("~/Views/Home/Login.cshtml");
        }
    }

    public string AuthenticateUser(string username, string password)
    {
        if(password.Equals("123")
            return "Super"
        else
            return null;
    }

    public ActionResult LogOff()
    {
        Session["UserName"] = null;
        //AuthenticationManager.SignOut();
        return View("~/Views/Home/Login.cshtml");
    }
}

And this is my action filter attempt:

public class AuthorizationFilter : ActionFilterAttribute
{
    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        if (HttpContext.Current.Session["UserName"] != null)
        {
            filterContext.Result = new RedirectToRouteResult(
                   new RouteValueDictionary{{ "controller", "MainPage" },
                                      { "action", "Default" }

                                     });
        }
        base.OnActionExecuting(filterContext);
    }
}

I have already added it to FilterConfig, but when I login it does not load Default.cshtml it just keeps looping the action filter. The action result for it looks like this:

//this is located in the MainPage controller

 [AuthorizationFilter]
    public ActionResult Default()
    {
        return View("~/Views/Home/Default.cshtml");
    }

So, what would I need to add in order to give authorization so only authenticated users can view the application´s pages? Should I use Session variables or is there another/better way of doing this using? I am pretty much stuck with AuthenticateUser(), since what happens there now is just a simple comparison like the one we have there now.

Thank you for your time.

5
  • Just to clarify, you added your AuthorizationFilter to the FilterConfig? Commented May 21, 2015 at 11:14
  • @WillSmith yes, i added it to FilterConfig Commented May 21, 2015 at 11:14
  • Why can't you use the built in [Authorize] attribute on your controller? Commented May 21, 2015 at 11:19
  • @Coulton how could i use when my AuthenticateUser looks like that? Serious question, from what i have read in a situation like this I have to build my own. Commented May 21, 2015 at 11:21
  • Instead of creating a standard FilterAttribute, create it as an AuthorizationAttribute msdn.microsoft.com/en-us/library/ee707357%28v=vs.91%29.aspx Commented May 21, 2015 at 11:31

3 Answers 3

7

Create an AuthorizeAttribute with your logic in there:

public class AuthorizationFilter : AuthorizeAttribute, IAuthorizationFilter
{
    public void OnAuthorization(AuthorizationContext filterContext)
    {
        if (filterContext.ActionDescriptor.IsDefined(typeof(AllowAnonymousAttribute), true)
            || filterContext.ActionDescriptor.ControllerDescriptor.IsDefined(typeof(AllowAnonymousAttribute), true))
        {
            // Don't check for authorization as AllowAnonymous filter is applied to the action or controller
            return;
        }

        // Check for authorization
        if (HttpContext.Current.Session["UserName"] == null)
        {
            filterContext.Result = new HttpUnauthorizedResult();
        }
    }
}

As long as you have the Login URL Configured in your Startup.Auth.cs file, it will handle the redirection to the login page for you. If you create a new MVC project it configures this for you:

public partial class Startup
{
    public void ConfigureAuth(IAppBuilder app)
    {
        app.UseCookieAuthentication(
            new CookieAuthenticationOptions {

                    // YOUR LOGIN PATH
                    LoginPath = new PathString("/Account/Login")
            }
        );
    }
}

Using this you can decorate your controllers with [AuthorizationFilter] and also [AllowAnonymous] attributes if you want to prevent the authorization from being checked for certain Controllers or Actions.

You might want to check this in different scenarios to ensure it provides tight enough security. ASP.NET MVC provides mechanisms that you can use out of the box for protecting your applications, I'd recommend using those if possible in any situation. I remember someone saying to me, if you're trying to do authentication/security for yourself, you're probably doing it wrong.

Sign up to request clarification or add additional context in comments.

5 Comments

I did some research and it seems that overriding onAuthorization is a bad idea because it does some special stuff to avoid caches from serving up pages.
Thanks for letting me know. I'd be interested to know more details about that, have you got a link?
I read the source code, there is a big important notice in it about exactly that. github.com/ASP-NET-MVC/aspnetwebstack/blob/master/src/…
Since each request has to be checked for authenticatication first anyway, I simple overwrite the AuthorizationCore function instead and do all the logic in there.
Sounds like a reasonable solution. Thanks for bringing this to my attention, I haven't touched any of the caching mechanisms for ASP.NET MVC yet, so I'll bare this in mind when I do!
1

Since your attribute is added to the FilterConfig, it will apply to ALL actions. So when you navigate to your MainPage/Default action it will be applying the filter and redirecting you to your MainPage/Default action (and so on...).

You will either need to:

  • remove it from the FilterConfig and apply it to the appropriate actions / controllers
  • or add an extra check in the filter so that it doesn't redirect on certain routes

2 Comments

thanks for the answers, i tried the first one, removing it from FilterConfig but it stopped working, thinking on adding that extra check to prevent it from re directing to the same page over and over again.
You could also look into using the built in AuthenticationAttribute & FormsAuthentication
0

You can simply access Session Object from OnAuthorization method like this :

public void OnAuthorization(AuthorizationFilterContext context)
            {            
                //Log("OnAuthorization", context.RouteData);
                var user = context.HttpContext.Session.GetString("user");
              
                if (user == null) {

                  // context.Result = new UnauthorizedResult(); //use this if you want send 401 Http Response or                                             
                  context.Result = new RedirectResult("home/login");
                }        
    
            }

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.