2

My project got pages with [Authorize] where user have to log in to visit those pages.

Upon successful login with same userid and password as in database, the current users id get stored in session. But how do I do I authenticate/allow user to visit pages with [Authorize]?

[HttpPost]
    [ValidateAntiForgeryToken]
    public ActionResult Login(User u)
    {

        if (ModelState.IsValid) //this is check validity
        {

            using (UserEntities db = new UserEntities())
            {

                var v = db.Users.Where(a=>a.UserName.Equals(u.UserName) && a.Password.Equals(u.Password)).FirstOrDefault();
                if (v != null)
                {
                    Session["LoggedUserID"] = u.Id.ToString();
                    Session["UserFullname"] = u.Name.ToString();

                    return RedirectToAction("AfterLogin");

                }

            }
        }
        return View(u);
    }

Any help is much appreciate. Thanks.

skylake
  • 409
  • 2
  • 9
  • 24

2 Answers2

4

If you absolutely want to manage login and security yourself using Session, You can create your own action filter which checks whether session has a user id set to it.

Something like this

public class AuthorizeWithSession : ActionFilterAttribute
{       
    public override void OnActionExecuting(ActionExecutingContext context)
    {
        if (context.HttpContext.Session == null ||
                                      context.HttpContext.Session["LoggedUserID"]==null)
        {
            context.Result =
                new RedirectToRouteResult(new RouteValueDictionary(
                                     new {controller = "Account", action = "Login"}));
        }
        base.OnActionExecuting(context);
    }
}

Now decorate this action filter on your secure actions/controllers

[AuthorizeWithSession]
public class TeamController : Controller
{
}
Shyju
  • 214,206
  • 104
  • 411
  • 497
  • Ah thanks, but where should I put that class in MVC? I'm pretty new and all these sorting is still confusing. – skylake Sep 26 '16 at 01:28
  • Having problem with TryGetValue as I get following error - ..`is inaccessible due to its protection level. Cannot resolve symbol TryGetValue`.` Not sure how to tackle that. – skylake Sep 26 '16 at 01:37
  • 1
    Ah! that code was for aspnet core. For other version of MVC, you can do a null check for that key ( Answer updated). You can put this class anywhere in your project. I prefer to create a directory called "Filters" and put all filters under that. – Shyju Sep 26 '16 at 02:07
  • For security, you should inherit from AuthorizeAttribute and not ActionFilterAttribute – Haitham Shaddad Sep 26 '16 at 05:34
1

You should have your own role management if you want to control what the users can do. Each user should have one or more roles, each role can have a set of permissions and you can create an action filter that inherits from AuthorizeAttribute to make sure it is executed as early as possible.

Inside the AuthorizeCore method of the AuthorizeAttribute , you will see if the user is authenticated or not, and if he is authenticated then you can read his identity, read his roles and permissions from the database and compare it to a value passed to the role.

ex:

 public class RequireRoleAttribute : AuthorizeAttribute
    {
        public RoleEnum[] RequiredRoles { get; set; }


        public RequireRoleAttribute()
        {

        }

        public RequireRoleAttribute(params RoleEnum[] roles)
            : this()
        {
            RequiredRoles = roles;
        }

        protected override bool AuthorizeCore(HttpContextBase httpContext)
        {
            var principle = httpContext.User;

            if (principle == null || principle.Identity == null || !principle.Identity.IsAuthenticated)
            {
                return false;
            }

            if (RequiredRoles != null)
            {
                if (!HasRole(RequiredRoles))
                {
                    httpContext.Response.Redirect("/AccessDenied");
                }
            }

            return base.AuthorizeCore(httpContext);
        }


        public bool HasRole(RoleEnum[] roles)
        {
            foreach (var role in roles)
            {
                if (HasRole(role))
                    return true;
            }

            return false;
        }

        public bool HasRole(RoleEnum role)
        {
            return true if the user role has the role specified (read it from database for example)
        }
    }

Then in your controller, just annotate the controller or action with the attribute

    [RequireRole(RoleEnum.Administator)]
    public class MySecureController : Controller
    {
    }
Haitham Shaddad
  • 4,336
  • 2
  • 14
  • 19
  • Thanks for enlightenment. `RoleEnum[]` cant be resolved, how do I deal with it? – skylake Sep 26 '16 at 11:54
  • 1
    RoleEnum[] is just an enum that has your list of roles, ex: Customer, Administrator, User. ` Public enum RoleEnum { Administrator, Customer }` – Haitham Shaddad Sep 27 '16 at 05:11