ASP.NET会员资格密码过期

23
我正在使用ASP.NET Membership对我的Web应用进行身份验证,这对我非常有效。现在我必须实现密码过期。
如果密码已过期,则应将用户重定向到ChangePassword屏幕,并且不允许访问任何其他部分的应用程序,直到更改密码为止。
有许多aspx页面。一个解决方案可以是如果密码已过期,则在每个aspx的OnInit中重定向到ChangePassword屏幕。是否有其他解决方案或建议。
谢谢, Jai
6个回答

29

参考csgero的回答,我发现在ASP.Net 2.0 (3.5)中不需要显式地为此事件添加事件处理程序。

您只需在global.asax中创建以下方法,它会自动连接:

void Application_PostAuthenticateRequest(object sender, EventArgs e)
{
    if (this.User.Identity.IsAuthenticated)
    {
        // get user
        MembershipUser user = Membership.GetUser();

        // has their password expired?
        if (user != null
            && user.LastPasswordChangedDate.Date.AddDays(90) < DateTime.Now.Date
            && !Request.Path.EndsWith("/Account/ChangePassword.aspx"))
        {
            Server.Transfer("~/ChangePassword.aspx");
        }
    }
}

请注意Ben Rethmeier在下面提供的修复方法(https://dev59.com/HXRC5IYBdhLWcg3wSu97#9879682),以便在更改密码屏幕上更改密码。 - joshschreuder
谢谢@shrodes - 我已经更新了我的答案,包括Ben Rethmeier的修复 :o) - Andrew

13
您可以在global.asax文件中为HttpApplication.PostAuthenticateRequest事件添加事件处理程序,并在那里处理重定向。

6
结合使用Membership Provider的LastPasswordChangedDate属性来确定密码何时过期,这就是我会做的。 - technophile

9

进一步参考安德鲁的回答,我发现您需要检查用户是否已经在修改密码页面上,否则他们将永远无法实际更改密码,因此永远无法离开修改密码页面:

void Application_PostAuthenticateRequest(object sender, EventArgs e)
    {
        if (this.User.Identity.IsAuthenticated)
        {
            // get user 
            MembershipUser user = Membership.GetUser();

            // has their password expired? 
            if (user != null
                && user.LastPasswordChangedDate.AddMinutes(30) < DateTime.Now
                && !Request.Path.EndsWith("/Account/ChangePassword.aspx"))
            {
                Server.Transfer("~/Account/ChangePassword.aspx");
            }
        }
    } 

6

我只用了一个小时就实现了这个功能,无需修改基本页面。以下是实现步骤:

  1. 响应 membership 控件的 LoggingIn 事件

  2. 在 membership 数据库中查找用户并获取 LastPasswordChangedDate

  3. 使用 TimeSpan 将此日期与当前日期进行比较,并决定密码是否在要求的天数之前最后更改。 我从 web.config 中获取此值

  4. 如果密码已过期,则重定向到 ChangePassword 页面


1
这不会捕获已经存在授权票据(“记住我”)的用户。csgero的解决方案是正确的。 - Brett
如果他们已经通过身份验证,我认为这不是什么大问题,除非你将cookies有效期设置为无限。也许,如果你检测到他们已经登录但过期了,那么每次只需将cookie设置为在20分钟左右过期。然后,当他们回来时,他们必须更改它。 - Andrew
1
在PostAuth中进行检查的问题是每个请求都会增加大量的系统活动。只要您的票据相当经常过期,就不应该有太大的问题,或者您可以在超时时间之后运行PostAuth代码+1天。这样可以确保任何使用有效的表单验证票证击打站点的人都会被检查。然后,如果他们在那段时间内根本没有登录,表单验证票证将过期,甚至可以使用LogginIn。在超过票证过期时间的一天后,您可以删除PostAuth事件。此外,您还需要在登录时进行检查。 - Adam Tuliper
并在其密码过期时强制使他们的票证在最大时间内过期。这可以防止那些在令牌到期之前就过期的情况。 - Adam Tuliper
这不会捕捉到仅仅从更改密码屏幕导航离开的用户。他们刚刚通过身份验证,可以继续使用。这就是为什么你必须检查每个请求,尽管它不够优雅。 - philw

4

我在这里寻找解决方案,但我的当前技术是ASP.NET MVC。因此为了帮助其他人:您可以扩展AuthorizeAttribute并覆盖OnAuthorization方法,像这样:

public class ExpiredPasswordAttribute : AuthorizeAttribute
{
    public override void OnAuthorization(AuthorizationContext filterContext)
    {
        IPrincipal user = filterContext.HttpContext.User;

        if(user != null && user.Identity.IsAuthenticated)
        {
            MembershipUser membershipUser = Membership.GetUser();

            if (PasswordExpired) // Your logic to check if password is expired...
            {
                filterContext.HttpContext.Response.Redirect(
                    string.Format("~/{0}/{1}?{2}", MVC.SGAccount.Name, MVC.SGAccount.ActionNames.ChangePassword,
                    "reason=expired"));

            }
        }

        base.OnAuthorization(filterContext);
    }
}

注意:我在上面的代码中使用 T4MVC 来检索控制器和操作名称。
除了“AccountController”之外,将所有控制器都标记为此属性。这样,任何具有过期密码的用户都无法浏览网站。
这是我在ASP.NET MVC中关于此主题所做的一篇帖子,其中包含一些奖励点: ASP.NET MVC中用户密码过期过滤器属性

0

我使用了上面的代码,并进行了轻微修改以在Asp.NET(4.5)MVC5中实现,使用了.NET身份提供程序。只是留在这里给下一个人使用 :)

void Application_PostAuthenticateRequest(object sender, EventArgs e)
    {
        if (this.User.Identity.IsAuthenticated)
        {
            WisewomanDBContext db = new WisewomanDBContext();

            // get user
            var userId = User.Identity.GetUserId();
            ApplicationUser user = db.Users.Find(userId);

            // has their password expired?
            if (user != null && user.PasswordExpires <= DateTime.Now.Date
                && !Request.Path.EndsWith("/Manage/ChangePassword"))
            {
                Response.Redirect("~/Manage/ChangePassword");
            }

            db.Dispose();
        }
    }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接