【问题标题】:Redirect to returnURL not working重定向到 returnURL 不起作用
【发布时间】:2012-05-03 12:07:15
【问题描述】:

参考this posted question

给出的答案对我不起作用,我在这里遇到了同样的问题。

我也在使用 aspnet 身份验证,用户可以尝试导航到网站上的任何页面,特别是用户导航到 /mycontroller/myaction/25 之类的内容非常常见,其中 25 是帐户或产品该用户经常使用的标识符。

如果用户在尝试访问该 url 时当前未通过身份验证,他们将被重定向到登录屏幕。登录后,redirect(returnURL) 不会将用户导航到请求的页面。该页面停留在登录屏幕上。

用户在登录前粘贴到地址栏中的 url 可以是:

http://localhost:4082/Account/LogOn?ReturnUrl=%2fProduct%2fEdit%2f59

输入凭据并调试后看到凭据通过了身份验证,URL是一样的

http://localhost:4082/Account/LogOn?ReturnUrl=%2fProduct%2fEdit%2f59

stock mvc 项目和我的不同之处在于,我在登录操作中发生的不仅仅是登录。这是我的代码:(显然,我通过使每个函数变小并包含在内而破坏了某些东西)

public ActionResult LogOn() {
    if (User.Identity.IsAuthenticated)
        return RedirectToAction("Index", "Home");
    var model = new LogOnViewModel();
    return View(model);
}

[HttpPost]
public ActionResult LogOn(LogOnViewModel model, string returnUrl) {
    if (ModelState.IsValid) {
        try {
            return AttemptToAuthenticateUser(model, returnUrl);
        }
        catch (Exception ex) {
            ModelState.AddModelError("", ex.Message);
        }
    }
    return View(model);
}

private ActionResult AttemptToAuthenticateUser(LogOnViewModel model, string returnUrl) {
    var membershipUser = GetUserFromMembershipProvider(model.Username, false);
    var audit = new LoginAudit(model.Username, model.Password, Request.Browser.Browser, Request.Browser.Type, Request.UserHostAddress);
    VerifyUserAccountIsApprovedNotLockedOut(membershipUser);
    AuthenticateCredentials(model, audit);
    AuditLogon(audit, model.Username, true);
    return ForwardToLogonResultAction(membershipUser, returnUrl, model.RememberMe);
}

internal static MembershipUser GetUserFromMembershipProvider(string username, bool isUserCurrentlyLoggedIn) {
    var membershipUser = Membership.GetUser(username, isUserCurrentlyLoggedIn);
    if (membershipUser == null)
        throw new Exception("The user account was not found");
    return membershipUser;
}

internal static void VerifyUserAccountIsApprovedNotLockedOut(MembershipUser membershipUser) {
    if (membershipUser.IsLockedOut || !membershipUser.IsApproved)
        throw new Exception("This account has been disabled or has been locked out. Please contact Administration for support");
}

private void AuthenticateCredentials(LogOnViewModel model, LoginAudit audit) {
    if (Membership.ValidateUser(model.Username, model.Password)) { }
    else {
        AuditLogon(audit, model.Username, false);
        throw new Exception("The user name or password provided is incorrect");
    }
}

private void AuditLogon(LoginAudit audit, string username, bool isSuccessfullyAuthenticated) {
    if (isSuccessfullyAuthenticated)
        audit.Password = string.Empty;
    audit.Save(username);
}

private ActionResult ForwardToLogonResultAction(MembershipUser currentMembershipUser, string returnUrl, bool rememberMe) {
    if (IsPasswordOnAccountTemporary((Guid)currentMembershipUser.ProviderUserKey))
        return RedirectToAction("Edit", "ChangePassword");
    if (Url.IsLocalUrl(returnUrl) && returnUrl.Length > 1 && returnUrl.StartsWith("/") && !returnUrl.StartsWith("//") && !returnUrl.StartsWith("/\\")) {
        return Redirect(returnUrl);
    }
    return ForwardUserToHomePage(currentMembershipUser.UserName, rememberMe);
}

private bool IsPasswordOnAccountTemporary(Guid userGUID) {
    var profile = new Profile(userGUID);
    return profile.IsTemporaryPassword;
}

更新

我尝试更改 Post 操作,以便 returnURL 检查在同一个操作中,但它仍然不起作用:

    [HttpPost]
    public ActionResult LogOn(LogOnViewModel model, string returnUrl) {
        if (ModelState.IsValid) {
            try {
                AttemptToAuthenticateUser(model, returnUrl);
                if (Url.IsLocalUrl(returnUrl) && returnUrl.Length > 1 && returnUrl.StartsWith("/") && !returnUrl.StartsWith("//") && !returnUrl.StartsWith("/\\")) 
                    return Redirect(returnUrl);
                return ForwardUserToHomePage(model.Username, model.RememberMe);
            }
            catch (Exception ex) {
                ModelState.AddModelError("", ex.Message);
            }
        }
        return View(model);
    }

更新 2 将我的代码改回原来的方式,它运行良好......所以这告诉我,它与我正在做的事情的顺序有关......排序较小的方法以匹配此操作的顺序,看看会发生什么

    [HttpPost]
    public ActionResult LogOn(LogOnViewModel model, string returnUrl) {
        if (ModelState.IsValid) {
            MembershipUser currentUser;
            var audit = new LoginAudit(model.Username, model.Password, Request.Browser.Browser, Request.Browser.Type, Request.UserHostAddress);
            if (Membership.ValidateUser(model.Username, model.Password)) {
                audit.Password = string.Empty;
                FormsAuthentication.SetAuthCookie(model.Username, model.RememberMe);
                currentUser = Membership.GetUser(model.Username, true);
                if (currentUser != null && currentUser.ProviderUserKey != null) {
                    var profile = new Profile((Guid)currentUser.ProviderUserKey);
                    if (profile.IsTemporaryPassword)
                        return RedirectToAction("Edit", "ChangePassword");
                }
                if (Url.IsLocalUrl(returnUrl) && returnUrl.Length > 1 && returnUrl.StartsWith("/")
                    && !returnUrl.StartsWith("//") && !returnUrl.StartsWith("/\\")) {
                    return Redirect(returnUrl);
                }
                return RedirectToAction("Index", "Home");
            }
            currentUser = Membership.GetUser(model.Username, false);
            if (currentUser != null && (currentUser.IsLockedOut || !currentUser.IsApproved)) {
                ModelState.AddModelError("", "This account has been locked out. Please contact ELM Administration for support.");
            }
            else {
                ModelState.AddModelError("", "The user name or password provided is incorrect.");
            }
            audit.Save(model.Username);
        }
        return View(model);
    }

更新 3

这解决了它,我自己搞定的:-)

    private void AuthenticateCredentials(LogOnViewModel model, LoginAudit audit) {
        if (Membership.ValidateUser(model.Username, model.Password)) {
            FormsAuthentication.SetAuthCookie(model.Username, model.RememberMe);
        }
        else {
            AuditLogon(audit, model.Username, false);
            throw new Exception("The user name or password provided is incorrect");
        }
    }

【问题讨论】:

    标签: asp.net-mvc-3


    【解决方案1】:

    在您的Logon 视图中,您是否将 url 传递给 HttpPost 方法?

     @using (Html.BeginForm("LogOn", "Account", new { returnUrl= Request.QueryString["ReturnUrl"] }))
     {
         //your form elements
       <input type="submit" value="Login" />
     }
    

    【讨论】:

    • 我正在使用没有参数的 beginform 只是 @Html.BeginForm()
    • @CDSmith:您的 HttpPost 操作方法需要一个名为 returnUrl 的参数,因此您应该传递它。像我的回答一样更改您的表格。
    • 我不需要更改它,因为 - 请参阅更新 - 在我最初的操作中,表单没有通过 returnUrl 并且它运行良好。开箱即用的 MVC3,returnUrl 不必在表单中指定。因此,由于原始操作在没有指定的情况下有效,所以我可以看到问题更多是关于我正在做的所有垃圾的排序。我怀疑这与在原始操作早期设置的 cookie 有关。
    • 是的,就是这样,我修改了 AuthenticateCredentials 方法,但它工作得很好,不是......请参阅更新 3
    【解决方案2】:

    解决方法是比我之前更早地设置 cookie。仅当我调用设置 cookie 的 ForwardUserToHomePage 方法然后重定向到 home/index 时,我才设置 cookie。但是由于该方法从未被调用,因为我正在执行 redirect(returnUrl) 而不是设置 cookie。由于未设置,重定向失败,因为客户端认为以前尚未登录,因此实际上登录页面“再次被点击”。

    将我的 AuthenticateCredentials 方法修改为:

        private void AuthenticateCredentials(LogOnViewModel model, LoginAudit audit) {
            if (Membership.ValidateUser(model.Username, model.Password)) {
                FormsAuthentication.SetAuthCookie(model.Username, model.RememberMe);
            }
            else {
                AuditLogon(audit, model.Username, false);
                throw new Exception("The user name or password provided is incorrect");
            }
        }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-09-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-05-24
      • 2014-02-04
      • 2014-03-10
      相关资源
      最近更新 更多