MVC会话到期 - 继续左侧

时间:2013-10-22 13:09:50

标签: asp.net asp.net-mvc session

我们有一个需要登录的内部ASP.NET MVC应用程序。登录工作很好,并做了预期的事情。我们的会话有效期为5分钟。在该段时间内坐在单个页面上之后,用户已经丢失了会话。如果他们尝试刷新当前页面或浏览到另一个页面,他们将获得登录页面。

我的问题是(在重新登录之后)告诉MVC重定向到他们的(刷新/浏览)尝试,而不是总是获得HOME控制器页面?

3 个答案:

答案 0 :(得分:3)

通常这应该自动发生。当匿名用户命中受保护资源时(由于会话过期,他是匿名用户),FormsAuthentication模块会拦截此请求,并通过附加loginUrl查询字符串重定向到您在web.config中注册的ReturnUrl指向受保护资源的参数。

因此,例如,如果您将~/Account/LogOn配置为登录网址,并且匿名用户尝试点击~/Foo/Bar受保护资源,则会将其重定向到~/Account/LogOn?ReturnUrl=%2FFoo%2FBar

然后,他将看到一个登录页面,他将输入他的凭据并将表单提交给[HttpPost]控制器上的LogOn Account操作。凭证将被验证,如果有效,将生成新的表单身份验证cookie,并将用户重定向到最初请求的受保护资源。

以下是LogOn操作中的相应代码:

[HttpPost]
public ActionResult LogOn(LogOnModel model, string returnUrl)
{
    if (ModelState.IsValid)
    {
        if (Membership.ValidateUser(model.UserName, model.Password))
        {
            FormsAuthentication.SetAuthCookie(model.UserName, model.RememberMe);
            if (Url.IsLocalUrl(returnUrl) && returnUrl.Length > 1 && returnUrl.StartsWith("/")
                && !returnUrl.StartsWith("//") && !returnUrl.StartsWith("/\\"))
            {
                return Redirect(returnUrl);
            }
            else
            {
                return RedirectToAction("Index", "Home");
            }
        }
        else
        {
            ModelState.AddModelError("", "The user name or password provided is incorrect.");
        }
    }

    // If we got this far, something failed, redisplay form
    return View(model);
}

注意成功验证后如何将用户重定向到默认Home/IndexreturnUrl参数。

当然,我在这里讲述的所有故事都适用于Visual Studio创建的默认ASP.NET MVC模板。如果由于某种原因您修改了此模板,这可能会解释您正在观察的行为。

在任何情况下,从我的回答中要记住的事情是,如果您使用表单身份验证,模块将把ReturnUrl查询字符串参数传递给最初请求的受保护资源到配置的登录页面。因此,在成功进行身份验证后,您可以将用户重定向到此页面。

答案 1 :(得分:2)

创建新的ASP.Net MVC项目时,此功能已开箱即用。

简而言之,请求的URL作为参数发送到MVC框架的Index AccountController操作,然后成为登录页面URL的参数:

[AllowAnonymous]
public ActionResult Login(string returnUrl)
{
  ViewBag.ReturnUrl = returnUrl;

  return View();
}

当用户发布其凭据并且登录成功时,returnUrl用于将用户重定向到最初请求的页面:

[HttpPost]
[AllowAnonymous]
public ActionResult Login(LoginModel model, string returnUrl)
{
  if (ModelState.IsValid && Membership.ValidateUser(model.UserName, model.Password))
  {

    return RedirectToLocal(returnUrl);
  }

  // If we got this far, something failed, redisplay form
  ModelState.AddModelError("LogInIncorrectError", Resources.LogInIncorrectError);

  return View(model);
}

private ActionResult RedirectToLocal(string returnUrl)
{
  if (Url.IsLocalUrl(returnUrl))
  {
    return Redirect(returnUrl);
  }

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

我建议您创建一个新项目,看看它的行为......

请注意,这仅适用于HttpGet,如果用户提交表单,则无效。

答案 2 :(得分:2)

通常,这与ASP.NET MVC应用程序中的AccountController开箱即用。请查看默认的Login操作:

[AllowAnonymous]
public ActionResult Login(string returnUrl)
{
    ViewBag.ReturnUrl = returnUrl;
    return View();
}

[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public ActionResult Login(LoginModel model, string returnUrl)
{
    if (ModelState.IsValid && WebSecurity.Login(model.UserName, model.Password, persistCookie: model.RememberMe))
    {
        return RedirectToLocal(returnUrl);
    }

    // If we got this far, something failed, redisplay form
    ModelState.AddModelError("", "The user name or password provided is incorrect.");
    return View(model);
}

// later...
private ActionResult RedirectToLocal(string returnUrl)
{
    if (Url.IsLocalUrl(returnUrl))
        return Redirect(returnUrl);
    return RedirectToAction("Index", "Home");
}

当会话过期并且用户被重定向到登录页面时,系统应该为该重定向提供returnUrl参数。如果它不在您的应用程序中,那么您的应用程序中的内容与此情况下的默认值不同?

请注意第一个Login操作(仅在用户重定向到该页面后呈现登录页面)如何在ViewBag中包含该值。此页面的默认视图将值添加到form元素,以便它将包含在登录POST请求中。接收该请求的第二个Login操作会将用户定向到提供的URL(或默认值/Index/Home,如帮助方法中所示)。

您的应用程序是否正在维护这一系列事件?如果没有,这一系列事件会在哪里破裂?按照惯例,你应该是:

  1. 从会话到期重定向接收returnUrl
  2. 在登录表单中包含returnUrl
  3. 成功登录后将用户重定向到returnUrl