Как исправить проблему с перенаправлением пользователя для входа в систему после успешного завершения, но не на страницу пользователя?

В MVC4 я создал собственный поставщик членства, который возвращает true, если проверка подлинности пользователя проходит успешно. Здесь нет ничего страшного — эта часть работает так, как должна:

    public override bool ValidateUser(string username, string password)
    {
        var crypto = new SimpleCrypto.PBKDF2(); // type of encryption
        // TODO: using (var unitOfWork = new Website.Repository.UnitOfWork(_dbContext))
        //var unitOfWork1 = new Website.Repository.UnitOfWork(_dbContext);

        using (var db = new Website.DAL.WebsiteDbContext())
        {
            var user = db.Users
                .Include("MembershipType")
                .FirstOrDefault(u => u.UserName == username);
            if (user != null && user.Password == crypto.Compute(password, user.PasswordSalt))
            {
                FormsAuthentication.SetAuthCookie(username, true);
                return true;
            }
        }
        return false;
    }

В моем действии входа:

    [HttpPost]
    [AllowAnonymous]
    public ActionResult Login(Models.UserModel user)
    {
        if (ModelState.IsValid)
        {
            // custom membership provider
            if (Membership.ValidateUser(user.UserName, user.Password))
            {
                // Cannot use this block as user needs to login twice
                //if (User.IsInRole("WaitConfirmation"))  // checks the custom role provider and caches based on web.config settings
                //{
                //    //TempData["EmailAddress"] = thisUser.Email;

                //    // email address has not yet been confirmed
                //    return RedirectToAction("WaitConfirmation");
                //    //return View("Account", thisUser)
                //}
                //else
                //{
                //    // get custom identity - user properties
                //    string userName = UserContext.Identity.Name;
                //    //CustomIdentity identity = (CustomIdentity)User.Identity;
                //    var identity = UserContext.Identity;
                //    int userId = identity.UserId;

                //    return RedirectToAction("Index", "Dashboard");
                //}

                if (User.Identity.IsAuthenticated && User.IsInRole("WaitConfirmation"))  // checks the custom role provider and caches based on web.config settings
                {
                    return RedirectToAction("WaitConfirmation");
                }
                else if (User.Identity.IsAuthenticated)
                {
                    // get custom identity - user properties
                    string userName = UserContext.Identity.Name;

                    return RedirectToAction("Index", "Dashboard");
                }
            }
            else
            {
                ModelState.AddModelError("", "Login data is incorrect.");
            }
        }

        return View(user);
    }

При выполнении кода, когда пользователь впервые входит в систему, User.Identity.IsAuthenticated имеет значение false, и страница перенаправляется обратно на страницу входа. В этот момент, если я либо:

  • вручную перейдите на страницу пользователя (Dashboard), сведения о пользователе доступны
  • войдите снова, это работает

Я считаю, что ответ заключается где-то в том, почему User.Identity.IsAuthenticated не сразу true, но не могу понять, что это неверно в первый раз.

Первый блок закомментированного кода завершается с ошибкой Unable to cast object of type 'System.Security.Principal.GenericIdentity' to type 'Website.AdminWebsite.Infrastructure.CustomIdentity', так как проверка IsAuthenticated отсутствует.

Предложения?


person ElHaix    schedule 08.01.2014    source источник


Ответы (2)


В этом посте описана проблема с похожими симптомами.

http://forums.asp.net/t/1177741.aspx

Пожалуйста, прочтите и убедитесь в порядке ваших событий (например, Аутентификация, Вход в систему)

person mcsilvio    schedule 08.01.2014
comment
Итак, они говорят, что нет необходимости проверять User.Identity.IsAuthenticated позже, потому что, очевидно, если Membership.ValidateUser истинно, то они авторизованы? Я должен буду попробовать это завтра. - person ElHaix; 08.06.2015

После прочтения статьи, предложенной @mcsilvio, я добавил RedirectToAction() следующим образом, чтобы инициировать новый жизненный цикл страницы:

    public ActionResult Login(Models.UserModel user)
    {
        if (ModelState.IsValid)
        {
            // custom membership provider
            if (Membership.ValidateUser(user.UserName, user.Password))
            {
                return RedirectToAction("VerifyIdentity", user);
            }
            else
            {
                ModelState.AddModelError("", "Login data is incorrect.");
            }
        }

        return View(user);
    }

    public ActionResult VerifyIdentity(Models.UserModel user)
    {
        if (User.Identity.IsAuthenticated && User.IsInRole("WaitConfirmation"))  // checks the custom role provider and caches based on web.config settings
        {
            return RedirectToAction("WaitConfirmation");
        }
        else if (User.Identity.IsAuthenticated)
        {
            // get custom identity - user properties
            string userName = UserContext.Identity.Name;

            return RedirectToAction("Index", "Dashboard");
        }

        return View(User);
    }

Это помогло, но мне интересно, есть ли лучший способ или это всегда делается так?

person ElHaix    schedule 08.01.2014
comment
Это одно из решений, но зачем лишнее путешествие по странице. Должен быть какой-то способ. - person Ali; 28.05.2015