【问题标题】:About Response.Redirect, FormsAuthentication and MVC关于 Response.Redirect、FormsAuthentication 和 MVC
【发布时间】:2012-12-20 07:43:51
【问题描述】:

我想了解调用FormsAuthentication.RedirectFromLoginPage 与调用Response.Redirect(FormsAuthentication.GetRedirectUrl()) 并手动重定向时程序行为的区别。

请看下面的cmets。

我有一个LoginController/Index(两个操作,一个用于HttpGet,一个用于HttpPost)。该控制器的 View 代表应用程序的登录页面。

我还有一个主页或登录页面,即用户成功登录后必须转到的页面。这在我的应用程序中由 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 也在LoginController 类上调用Index() 操作。

【问题讨论】:

    标签: asp.net asp.net-mvc forms-authentication response.redirect


    【解决方案1】:

    实际区别在于 FormsAuthentication.RedirectFromLoginPage() 设置 cookie 然后进行重定向,但 FormsAuthentication.GetRedirectUrl() 只返回重定向 url。

    有趣的是 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)。

    【讨论】:

      【解决方案2】:

      同意瓦西里的观点。 RedirectFromLoginPage 发出身份验证票证,并使用SetAuthCookie 方法将其放入默认 cookie。
      您可以阅读有关此行为的信息here

      如果您想更好地控制 cookie 创建(加密、过期、扩展主体),您应该自己创建 cookie。
      我解释了整个过程herehere

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-07-25
        • 2010-10-25
        • 2014-08-03
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多