C# 如何使用ASP.NET Identity Framework设置密码过期
我有一个使用Identity的ASP.NET项目。对于有关密码的身份配置,将使用C# 如何使用ASP.NET Identity Framework设置密码过期,c#,asp.net,passwords,asp.net-identity,C#,Asp.net,Passwords,Asp.net Identity,我有一个使用Identity的ASP.NET项目。对于有关密码的身份配置,将使用PasswordValidator。如何将密码的强制执行扩展到PasswordValidator当前拥有的(RequiredLength,RequiredDigit等)之外,以满足要求密码在N天后过期的要求?ASP.NET Identity 2中没有内置此类功能。最简单的方法是在用户上添加一个字段,如LastPasswordChangedDate。然后在每次授权期间检查此字段 public class Applica
PasswordValidator
。如何将密码的强制执行扩展到PasswordValidator
当前拥有的(RequiredLength
,RequiredDigit
等)之外,以满足要求密码在N天后过期的要求?ASP.NET Identity 2中没有内置此类功能。最简单的方法是在用户上添加一个字段,如LastPasswordChangedDate。然后在每次授权期间检查此字段
public class ApplicationOAuthProvider : OAuthAuthorizationServerProvider
{
public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
{
var user = await GetUser(context.UserName, context.Password);
if(user.LastPasswordChangedDate.AddDays(20) < DateTime.Now)
// user needs to change password
}
}
公共类ApplicationAuthProvider:OAuthAuthorizationServerProvider
{
公共重写异步任务GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentials上下文)
{
var user=await GetUser(context.UserName、context.Password);
if(user.LastPasswordChangedDate.AddDays(20)
在@Rikard的答案上添加
我将LastPasswordChangedDate
添加到我的ApplicationUser
模型中,如下所示:
public class ApplicationUser : IdentityUser
{
public DateTime LastPasswordChangedDate { get; set; }
public async Task<ClaimsIdentity> GenerateUserIdentityAsync(UserManager<ApplicationUser> manager)
{
// Note the authenticationType must match the one defined in CookieAuthenticationOptions.AuthenticationType
var userIdentity = await manager.CreateIdentityAsync(this, DefaultAuthenticationTypes.ApplicationCookie);
// Add custom user claims here
return userIdentity;
}
}
然后,在登录期间
,检查用户是否应重置密码。这只会在成功登录后进行检查,以免对用户造成太多的bug
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Login(LoginViewModel model, string returnUrl)
{
if (!ModelState.IsValid)
{
return View(model);
}
// This doesn't count login failures towards account lockout
// To enable password failures to trigger account lockout, change to shouldLockout: true
var result = await SignInManager.PasswordSignInAsync(model.Email, model.Password, model.RememberMe, shouldLockout: false);
switch (result)
{
case SignInStatus.Success:
var user = await UserManager.FindByNameAsync(model.Email);
if (user.LastPasswordChangedDate.AddDays(PasswordExpireDays) < DateTime.UtcNow)
{
return RedirectToAction("ChangePassword", "Manage");
}
else
{
return RedirectToLocal(returnUrl);
}
case SignInStatus.LockedOut:
return View("Lockout");
case SignInStatus.RequiresVerification:
return RedirectToAction("SendCode", new { ReturnUrl = returnUrl, RememberMe = model.RememberMe });
case SignInStatus.Failure:
default:
ModelState.AddModelError("", "Error: Invalid username or password");
return View(model);
}
}
@RickAnd MSFT下面的答案在哪里?@EricFalsken他在一年前发布了一个答案,但似乎被删除了。上述解决方案是处理密码退出的最简单和最好的方法。没有这样的内置功能。此时他们已登录。他们可以忽略更改密码。如何强制?如何注销它们?因此,在他们更改密码之前,他们无法做任何事情。因为你允许他们在移动到更改密码屏幕之前登录,用户难道不能点击不同的url,从而绕过更改密码吗?@JohnnyFun是对的。您应该在
Login
方法中使用CheckPasswordSignInAsync
而不是PasswordSignInAsync
来解决此问题
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Login(LoginViewModel model, string returnUrl)
{
if (!ModelState.IsValid)
{
return View(model);
}
// This doesn't count login failures towards account lockout
// To enable password failures to trigger account lockout, change to shouldLockout: true
var result = await SignInManager.PasswordSignInAsync(model.Email, model.Password, model.RememberMe, shouldLockout: false);
switch (result)
{
case SignInStatus.Success:
var user = await UserManager.FindByNameAsync(model.Email);
if (user.LastPasswordChangedDate.AddDays(PasswordExpireDays) < DateTime.UtcNow)
{
return RedirectToAction("ChangePassword", "Manage");
}
else
{
return RedirectToLocal(returnUrl);
}
case SignInStatus.LockedOut:
return View("Lockout");
case SignInStatus.RequiresVerification:
return RedirectToAction("SendCode", new { ReturnUrl = returnUrl, RememberMe = model.RememberMe });
case SignInStatus.Failure:
default:
ModelState.AddModelError("", "Error: Invalid username or password");
return View(model);
}
}
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<ActionResult> ChangePassword(ChangePasswordViewModel model)
{
if (!ModelState.IsValid)
{
return View(model);
}
var result = await UserManager.ChangePasswordAsync(User.Identity.GetUserId(), model.OldPassword, model.NewPassword);
if (result.Succeeded)
{
var user = await UserManager.FindByIdAsync(User.Identity.GetUserId());
if (user != null)
{
user.LastPasswordChangedDate = DateTime.UtcNow;
await UserManager.UpdateAsync(user);
await SignInManager.SignInAsync(user, isPersistent: false, rememberBrowser: false);
}
return RedirectToAction("Index", new { Message = ManageMessageId.ChangePasswordSuccess });
}
AddErrors(result);
return View(model);
}