1

This is a two-parter

Question 1 (the real question)

I have a DashboardController that is not tied to a model. A User must be logged in before they can access the dashboard. How can I run a check to see if a user is authenticated before every action is executed, and redirect them to the login view if not? I think OnActionExecuted is what I want, but I am not sure what the exact implementation should be. Am I on the right track here?

public class DashboardController : Controller
{
    private ApplicationContext db = new ApplicationContext();

    //
    // GET: /Admin/
    public ActionResult Index()
    {
        var categories = db.Categories.ToList();
        return View(categories);
    }

    public ActionResult Product(int id)
    {
        var product = db.Products.Find(id);
        return View(product);
    }

    protected override void OnActionExecuted(ActionExecutedContext filterContext)
    {
        if(Session["current_user"] == null)
        {
            // This (obviously) doesn't work - what should go here?
            return RedirectToAction("Create", "Session"); 
        }
        base.OnActionExecuted(filterContext);
    }
}

Question 2

If the user IS logged in, what is the right way to make the user accessible in all of these views? I have been told ViewBag is generally a bad idea - what should I use?

drewwyatt
  • 5,989
  • 15
  • 60
  • 106
  • 3
    Try the Authorize attribute. I'm not sure what you mean by your second question, what does the viewbag have to do with it? – CodeCaster Jul 01 '14 at 16:49
  • custom action filter sttribute – Ehsan Sajjad Jul 01 '14 at 16:51
  • Really, you should be doing authentication and authorization earlier in the HTTP pipeline. My normal method is an HTTP Module that uses the context authentication and authorize events using the IIdentity and IPrincipal interfaces. This way an unauthorized user can be redirected appropriately before any page loading occurs, and the application has current validated user credentials on every request that are accessible any where in the app. – Nick Zimmerman Jul 01 '14 at 16:52
  • @CodeCaster If the user is authenticated, I'd like to make that user accessible from the view. is there a way I can assign the user (stored in the session) to a value that can be accessed by every action in the view - so that I can do something like: `

    Hello @user.FirstName @user.LastName

    `
    – drewwyatt Jul 01 '14 at 16:52
  • @NickZimmerman I'm definitely open to doing this like that, do you have a link to an article or something? (or can you post an answer where you go into detail?) – drewwyatt Jul 01 '14 at 16:53

6 Answers6

2

I can authorize controllers and actions by follow this link: It's in brazilian portuguese originally, but the link below is translated to english.

https://translate.google.com.br/translate?sl=pt&tl=en&js=y&prev=_t&hl=pt-BR&ie=UTF-8&u=http%3A%2F%2Fdevbrasil.net%2Fprofiles%2Fblogs%2Fautentica-o-e-permiss-es-de-usu-rios-em-asp-net-mvc-4&edit-text=&act=url

You can get the logged user in views by

@HttpContext.Current.User.Identity.Name

PS: Sorry my bad english

Márcio Gonzalez
  • 1,020
  • 1
  • 8
  • 20
1

Use [Authorize] atrribute. For example:

    [AcceptVerbs(HttpVerbs.Get)]
    [Authorize]
    public ActionResult add()
    {

    }

Then in the web.config

<authentication mode="Forms">
  <forms name="my_cookie_name" loginUrl="~/login" defaultUrl="~/" timeout="2880"/>
</authentication>

If the user is not authenticated, it will get redirected automatically to the login page.

If you want something simple to control the identity of your users check the highest rated answer here: ASP.NET MVC - Set custom IIdentity or IPrincipal. It's a brilliant example. I use somthing similar in all my projects.

In my login action:

var user = _userService.system_login(systemlogin_model_post.email, systemlogin_model_post.password); // my user model 

//... doing all sorts of validations
// once everyone is happy I create a cookie

Response.Cookies.Add(UserCookie.GetCookie(user));

Than using the code from the link above I create cookie:

 public static class UserCookie
    {
        public static HttpCookie GetCookie(User user)
        {
            CustomPrincipalSerializeModel serializeModel = new CustomPrincipalSerializeModel { user_id = user.UserId, username = user.Username, roles = user.Roles ,session_token =  GUIDGenerator.ToAlphaNumerical() };
            JavaScriptSerializer serializer = new JavaScriptSerializer();
            string userData = serializer.Serialize(serializeModel);
            FormsAuthenticationTicket authTicket = new FormsAuthenticationTicket(1,
               user.UserId.ToString(),
               DateTime.Now,
               DateTime.Now.AddMinutes(30),
               false,
               userData);

            string encTicket = FormsAuthentication.Encrypt(authTicket);
            return  new HttpCookie(FormsAuthentication.FormsCookieName, encTicket);
        }
    }

When [Authorize] is fired this code takes care of it:

Global.asax

protected void Application_PostAuthenticateRequest(Object sender, EventArgs e)
        {
            HttpCookie authCookie = Request.Cookies[FormsAuthentication.FormsCookieName];

            if (authCookie != null)
            {
                FormsAuthenticationTicket authTicket = FormsAuthentication.Decrypt(authCookie.Value);

                JavaScriptSerializer serializer = new JavaScriptSerializer();

                CustomPrincipalSerializeModel serializeModel = serializer.Deserialize<CustomPrincipalSerializeModel>(authTicket.UserData);

                CustomPrincipal newUser = new CustomPrincipal(authTicket.Name);
                newUser.user_id = serializeModel.user_id;
                newUser.username = serializeModel.username;
                newUser.roles = serializeModel.roles;
                newUser.form_token = serializeModel.form_token;

                HttpContext.Current.User = newUser;
            }
        }
Community
  • 1
  • 1
Artur Kedzior
  • 3,994
  • 1
  • 36
  • 58
0

1) Authorize attribute of ASP.NET MVC is totally focused on your first problem. You may even go for customization but not suggested for most of scenarios.

2) To assign the currently logged in user and visible in all the views, you may bind the user name using ViewBag/ViewModel property to Layout(_Layout.cshtml) so that it appears on top of every page where the layout is used.

Note: If you want to perform any pre action-invoke logic, then OnActionExecuting filter is the correct place, before entering that action method.

Siva Gopal
  • 3,474
  • 1
  • 25
  • 22
0

Precisely, you have to create a class and that class inherits the Controller class.

public class MyAuthentication : Controller
{
  public MyAuthentication()
    {
        isAuthenticated();
    }  

    private void isAuthenticated()
    {
      // do your authentication


      //if user authenticated keep user details within a cookie, so that 
      // when the next request, program logic will search for cookie, 
      //if it is found then assume user was authenticated else redirect to login page.

    }
}

And then inherits this MyAuthentication class in your project for all controllers

public class DashboardController : MyAuthentication  
{

    public ActionResult Index()
    {
        var categories = db.Categories.ToList();
        return View(categories);
    }

    // rest of the codes
}

So that the authentication remains in single place. You can inherit this where ever you want.

Ondipuli
  • 468
  • 3
  • 9
  • I tried using this approach. But i am triggering an exception in the `isAuthenticated()` method. My logic was `if(Session["current_user"] == null) // do redirect`, but the exception says `Session["current_user"]` is not set to an instance of an object. How do I scope that out/circumvent the issue? – drewwyatt Jul 01 '14 at 17:43
  • Use like this System.Web.HttpContext.Current.Session["current_user"] instead of Session["current_user"] – Ondipuli Jul 02 '14 at 10:23
0

If you need current user anywhere in the controller/action then better way is to set the user data when you perform authorization.

In your authorization filter , you can use

System.Web.HttpContext.Current.Items["userdata"]=userDataObject;

For authentication , this article can help.

http://www.dotnet-tricks.com/Tutorial/mvc/G54G220114-Custom-Authentication-and-Authorization-in-ASP.NET-MVC.html

Ajay Kelkar
  • 4,591
  • 4
  • 30
  • 29
0

First Put the Form Authentication Cookie when the user is logged in. like

[HttpPost]
public ActionResult Login(Acccount obj){
// check whether the user login is valid or not
    if(UseIsValid){
        FormsAuthentication.SetAuthCookie(obj.username, obj.RememberMe);
        return redirectToAction("Index","DashBoard");
    }
    return View(obj);
}

* and Use [Authorize] attribute. like*

[Authorize]
public class DashboardController : Controller
{
    private ApplicationContext db = new ApplicationContext();

    public ActionResult Index()
    {
        var categories = db.Categories.ToList();
        return View(categories);
    }
}
Sunil Shrestha
  • 303
  • 1
  • 7