我想了解调用FormsAuthentication.RedirectFromLoginPage
与调用Response.Redirect(FormsAuthentication.GetRedirectUrl())
并手动重定向时的程序行为差异。
请参阅以下评论。
我有一个LoginController/Index
(两个操作,一个用于HttpGet
,另一个用于HttpPost
)。此控制器的视图表示应用程序的登录页面。
我还有一个主页或登录页面,即成功登录后用户必须登录的页面。这在我的应用程序中由HomeController's
Index
操作和~Views/Home/Index.cshtml
视图表示。
我提出了三种情景。我理解方案1,我希望它能像它那样工作,但我注意到方案2和3的区别。
情景1
namespace Controllers
{
[AllowAnonymous]
public class LoginController : Controller
{
[HttpPost]
public ActionResult Index(Login loginViewModel)
{
if (ModelState.IsValid)
{
var user = ValidateUser(loginViewModel);
if (user != null)
{
// Other stuff: set cookies, session state, etc.
return RedirectToAction("Index", "Home");
}
else
{
ModelState.AddModelError("", "Invalid password. Please try again.");
}
}
// If the user was a valid user, the flow-of-control won't reach here
// as expected and the user will be taken to the view that is served
// by the HomeController::Index() action. If it is by convention, it will
// be the ~Views/Home/Index.cshtml view. This is fine.
return View();
}
}
}
场景2
namespace Controllers
{
[AllowAnonymous]
public class LoginController : Controller
{
[HttpPost]
public ActionResult Index(Login loginViewModel)
{
if (ModelState.IsValid)
{
var user = ValidateUser(loginViewModel);
if (user != null)
{
// Other stuff: set cookies, session state, etc.
Response.Redirect(FormsAuthentication.GetRedirectUrl(loginViewModel.UserName,
loginViewModel.RememberMe));
}
else
{
ModelState.AddModelError("", "Invalid password. Please try again.");
}
}
// If the user was a valid user, the flow-of-control still reaches here
// as expected. And as expected, it renders the same View, i.e. the View
// associated with the controller we are in, which is ~Views/Login/Index,
// which represents the login page. This is wrong. I shouldn't redirect here.
// I understand this. My question here is two fold:
// 1) I am simply trying to understand the difference in behaviors of the three
// scenarios described in this question.
// 2) Given this, the right way would be to not use Response.Redirect here but instead
// use RedirectToAction. However, if I wanted to use Response.Redirect, what should
// I do?
return View();
}
}
}
场景3
namespace Controllers
{
[AllowAnonymous]
public class LoginController : Controller
{
[HttpPost]
public ActionResult Index(Login loginViewModel)
{
if (ModelState.IsValid)
{
var user = ValidateUser(loginViewModel);
if (user != null)
{
// Other stuff: set cookies, session state, etc.
FormsAuthentication.RedirectFromLoginPage(loginViewModel.UserName,
loginViewModel.RememberMe);
}
else
{
ModelState.AddModelError("", "Invalid password. Please try again.");
}
}
// If the user was a valid user, the flow-of-control still reaches here
// as expected. However, magically, somehow, even though the statement below
// suggests that the user must be taken to the View of the same controller and
// action that we are currently in, i.e. the View of the LoginController::Index()
// action, i.e. the ~Views/Login/Index.cshtml, it magically takes me to the
// ~Views/Home/Index.cshtml instead, which is what is specified as the LoginPage
// attribute of the <authentication>/<forms> element in the web.config.
// I want to know how this happens.
return View();
}
}
}
更新
我现在已经结束了。现在,即使使用RedirectToAction
的场景1 也会调用Index()
类的LoginController
操作。
答案 0 :(得分:1)
实际的不同之处在于FormsAuthentication.RedirectFromLoginPage()设置cookie然后进行重定向,但FormsAuthentication.GetRedirectUrl()仅返回重定向网址。
有趣的是FormsAuthentication.GetRedirectUrl()的实现是这样的:
public static String GetRedirectUrl(String userName, bool createPersistentCookie)
{
if (userName == null)
return null;
return GetReturnUrl(true);
}
因此实际上完全忽略了userName和createPersistentCookie参数。在调用GetRedirectUrl之前,必须手动调用FormsAuthentication.SetAuthCookie(userName,true / false)。
答案 1 :(得分:0)