How to redirect user to page after login?

Asked

Viewed 1,274 times

4

I am developing a web application, using Asp.Net MVC 5 com Identity and I’m using Roles to carry out the authorisation.

I’m trying to do that depending on the Role that the user has, it is directed to a different "Home" page.

Example:

  • Administrators => Home Administration;
  • Sellers => Home of the Commercial.

And so it goes. But I’m having a hard time finding a solution.

To redirect the user when denied access by Roles, I sub-wrote the method HandleUnauthorizedRequest:

  protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
    {
        if (!filterContext.HttpContext.User.Identity.IsAuthenticated)
        {
            // The user is not authenticated
            base.HandleUnauthorizedRequest(filterContext);
        }
        else if (!this.Roles.Split(',').Any(filterContext.HttpContext.User.IsInRole))
        {
            // The user is not in any of the listed roles => 
            // show the unauthorized view
            filterContext.Result = new ViewResult
            {
                ViewName = "~/Views/Shared/Page_403.cshtml"
            };
        }
        else
        {
            base.HandleUnauthorizedRequest(filterContext);
        }
    }

Now, to perform this redirect, after logging in? how would you do?

Controller Code Account:

        //
        // POST: /Account/Login
        [HttpPost]
        [AllowAnonymous]
        [ValidateAntiForgeryToken]
        public async Task<ActionResult> Login(LoginViewModel model, string returnUrl)
        {
            if (!ModelState.IsValid)
            {
                return View(model);
            }

            // This doesn't count login failures towards account lockout
            // To enable password failures to trigger account lockout, change to shouldLockout: true
            var result = await SignInManager.PasswordSignInAsync(model.Email, model.Password, model.RememberMe, shouldLockout: false);
            switch (result)
            {
                case SignInStatus.Success:
                    return RedirectToLocal(returnUrl);
                case SignInStatus.LockedOut:
                    return View("Lockout");
                case SignInStatus.RequiresVerification:
                    return RedirectToAction("SendCode", new { ReturnUrl = returnUrl, RememberMe = model.RememberMe });
                case SignInStatus.Failure:
                default:
                    ModelState.AddModelError("", "Invalid login attempt.");
                    return View(model);
            }
        }

When trying to validate using the condition: if(UserManager.IsInRole(User.Identity.GetUserId(), "admin")) error was generated:

inserir a descrição da imagem aqui

Code of HomeController:

public class HomeController : Controller
{
    [PermissoesFiltro]
    public ActionResult Index()
    {
        return View();
    }

    [PermissoesFiltro(Roles = "Comercial")]
    public ActionResult Index_Comercial()
    {
        return View();
    }

    [PermissoesFiltro(Roles = "Master")]
    public ActionResult Index_Master()
    {
        return View();
    }

Tables of Identity:

inserir a descrição da imagem aqui

  • You have not posted the code where you validate the login, you are using FormsAuth.SignIn? But it would be enough to execute one RedirectToAction. Might explain your problem better?

  • @Ricardopunctual I did a review and posted the controller code, I am using the standard that comes with Identity, which added login redirects to the default home. My doubt, it’s like checking the Role user and direct to different pages?

2 answers

6


There is a property of controller calling for User, once the login is successfully performed this property will have a value (information about the identity of the logged-in user). That’s not quite true, see update below;

This property will be "powered" by Identity and needs to implement the interface IPrincipal. In this interface, there is the method IsInRole(string role) which is exactly what you need.

I’m going to focus on the part of the code that really matters, what’s going to be done in there depends on what’s really needed for your project, you can do a database query to retrieve the URL, you can do more validations. The important thing is to understand that User.IsInRole serves exactly what you need.

case SignInStatus.Success:
    {        
        if(User.IsInRole("Admin")) // Se o usuário estiver na role admin
            return RedirectToLocal("UrlAdmin"); //Redireciona para uma URL pré-definida
        
        return RedirectToLocal(returnUrl);    
    }

Updating

In fact, the property User is still empty at the time of Login, so it will be necessary another strategy to recover the currently logged in user.

var user = await UserManager.FindAsync(model.Email, model.Password); 

if (UserManager.IsInRole(user.Id, "Admin"))
    return RedirectToAction("Home_Admin", "Controller"); //A forma de redirect que irá usar

UserManager is a property of AccountController.

  • Yeah, I already checked the name of role and this ok, at the moment I am registering the user in the scroll directly via bank, I have no methods deployed for this yet.

  • I made a review on asking, adding the error that was generated, while trying to validate in this way.

  • I’m using the default Identity deployment, all I did was change the view design.

  • Yes, I can, I already checked the tables of Identity and apparently they are ok, I’m trying like you said in a new application, I mean without any modification, I also added a print of the tables in the question

  • Friend, perfect, now it worked, just so I understand, you searched the user by email and password and then checked if he had the role right?

2

You can try to override the authorization method OnAuthorization, Passing the route values, by default are three route values: controller, action and area, the latter if there is an area. As you have already overwritten the method HandleUnauthorizedRequest, is consistent to overwrite the authorization also, leaving in one place the processing of redirects.

 public override void OnAuthorization(AuthorizationContext filterContext)
    {
        var dicRota = new Dictionary<string, object>();

        if (filterContext.HttpContext.User.IsInRole("Admin"))
        {
            dicRota.Add("controller", "Admin");
            dicRota.Add("action", "Home");
        }
        else if (filterContext.HttpContext.User.IsInRole("Vendedores"))
        {
            dicRota.Add("controller", "Comercial");
            dicRota.Add("action", "Home");
        }

        filterContext.Result = new RedirectToRouteResult(new RouteValueDictionary(dicRota));
    }
  • Friend, when trying to use your solution, the condition If I mean, he can verify the role user, however, does not access view, says it cannot be displayed, I have tested the view and are functioning normally.

  • Did you pass the correct controller and action names in the dictionary? In my examples I assume there are Admin and Commercial controllers, with their respective Home actions.

  • Yes, controller name = "home" action name = "index_commercial" and "index_master"

  • I needed to take a look at the Homecontroller.cs. file if you have it public ActionResult index_comercial(){ return View(); } it was supposed to work.

  • I made a review, putting the code.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.