1

参考这个发布的问题

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

我也在使用 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");
        }
    }
4

2 回答 2

7

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

 @using (Html.BeginForm("LogOn", "Account", new { returnUrl= Request.QueryString["ReturnUrl"] }))
 {
     //your form elements
   <input type="submit" value="Login" />
 }
于 2012-05-03T12:43:13.867 回答
0

解决方法是比我以前更早地设置 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");
        }
    }
于 2012-05-03T13:19:35.210 回答