我们有一个需要登录的内部ASP.NET MVC应用程序。登录工作很好,并做了预期的事情。我们的会话有效期为5分钟。在该段时间内坐在单个页面上之后,用户已经丢失了会话。如果他们尝试刷新当前页面或浏览到另一个页面,他们将获得登录页面。
我的问题是(在重新登录之后)告诉MVC重定向到他们的(刷新/浏览)尝试,而不是总是获得HOME控制器页面?
答案 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/Index
或returnUrl
参数。
当然,我在这里讲述的所有故事都适用于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
,如帮助方法中所示)。
您的应用程序是否正在维护这一系列事件?如果没有,这一系列事件会在哪里破裂?按照惯例,你应该是:
returnUrl
。returnUrl
。returnUrl
。