답변:
현재 릴리스에서
잊어 버린 비밀번호 재설정 요청에 대한 확인을 처리했다고 가정하면 다음 코드를 샘플 코드 단계로 사용합니다.
ApplicationDbContext =new ApplicationDbContext()
String userId = "<YourLogicAssignsRequestedUserId>";
String newPassword = "<PasswordAsTypedByUser>";
ApplicationUser cUser = UserManager.FindById(userId);
String hashedNewPassword = UserManager.PasswordHasher.HashPassword(newPassword);
UserStore<ApplicationUser> store = new UserStore<ApplicationUser>();
store.SetPasswordHashAsync(cUser, hashedNewPassword);
AspNet Nightly Build에서
ForgetPassword와 같은 요청을 처리하기 위해 토큰과 함께 작동하도록 프레임 워크가 업데이트되었습니다. 출시되면 간단한 코드 안내가 예상됩니다.
최신 정보:
이 업데이트는 더 명확한 단계를 제공하기위한 것입니다.
ApplicationDbContext context = new ApplicationDbContext();
UserStore<ApplicationUser> store = new UserStore<ApplicationUser>(context);
UserManager<ApplicationUser> UserManager = new UserManager<ApplicationUser>(store);
String userId = User.Identity.GetUserId();//"<YourLogicAssignsRequestedUserId>";
String newPassword = "test@123"; //"<PasswordAsTypedByUser>";
String hashedNewPassword = UserManager.PasswordHasher.HashPassword(newPassword);
ApplicationUser cUser = await store.FindByIdAsync(userId);
await store.SetPasswordHashAsync(cUser, hashedNewPassword);
await store.UpdateAsync(cUser);
또는 현재 암호를 모르고 어떻게 재설정 할 수 있습니까 (사용자가 암호를 잊어 버림)?
UserManager를 사용하여 비밀번호를 변경하고 싶지만 사용자의 현재 비밀번호를 제공하지 않으려는 경우 비밀번호 재설정 토큰을 생성 한 다음 대신 즉시 사용할 수 있습니다.
string resetToken = await UserManager.GeneratePasswordResetTokenAsync(model.Id);
IdentityResult passwordChangeResult = await UserManager.ResetPasswordAsync(model.Id, resetToken, model.NewPassword);
SecurityStamp
null이 아닌지 확인하십시오 . 이는 다른 데이터베이스에서 마이그레이션 된 사용자 또는 UserManager.CreateAsync()
방법을 통해 생성되지 않은 사용자에게 발생할 수 있습니다 .
이것이 원래의 대답이었습니다. 작동하지만 문제가 있습니다. 만약에 AddPassword
실패? 사용자는 암호없이 남겨집니다.
원래 답변 : 세 줄의 코드를 사용할 수 있습니다.
UserManager<IdentityUser> userManager =
new UserManager<IdentityUser>(new UserStore<IdentityUser>());
userManager.RemovePassword(userId);
userManager.AddPassword(userId, newPassword);
참조 : http://msdn.microsoft.com/en-us/library/dn457095(v=vs.111).aspx
그것은 그 해답 사용하는 것이 아마도 더 나은 EdwardBrey 제안 하고 DanielWright 나중에 정교 코드 샘플을.
당신에 UserManager
먼저 전화 GeneratePasswordResetTokenAsync을 . 사용자가 자신의 신원을 확인한 후 (예 : 이메일로 토큰 수신) 토큰을 ResetPasswordAsync에 전달합니다 .
ResetPasswordAsync
사용자 ID 사용 의 장점은 ID 공급자가 토큰이 아닌 사용자 ID 만 인덱싱하면된다는 것입니다. 이렇게하면 사용자가 많을 때 더 잘 확장 할 수 있습니다.
string message = null;
//reset the password
var result = await IdentityManager.Passwords.ResetPasswordAsync(model.Token, model.Password);
if (result.Success)
{
message = "The password has been reset.";
return RedirectToAction("PasswordResetCompleted", new { message = message });
}
else
{
AddErrors(result);
}
이 코드 조각은 github에서 사용할 수 있는 AspNetIdentitySample 프로젝트에서 가져온 것입니다.
방법 만들기 UserManager<TUser, TKey>
public Task<IdentityResult> ChangePassword(int userId, string newPassword)
{
var user = Users.FirstOrDefault(u => u.Id == userId);
if (user == null)
return new Task<IdentityResult>(() => IdentityResult.Failed());
var store = Store as IUserPasswordStore<User, int>;
return base.UpdatePassword(store, user, newPassword);
}
ASP.NET Identity에 대한 Microsoft 가이드가 좋은 시작이라고 생각합니다.
노트 :
AccountController를 사용하지 않고 비밀번호를 재설정하지 않으려면 Request.GetOwinContext().GetUserManager<ApplicationUserManager>();
. 동일한 OwinContext가 없다면 사용하는 DataProtectorTokenProvider
것과 같은 새로운 것을 만들어야 OwinContext
합니다. 기본적으로 App_Start -> IdentityConfig.cs
. 다음과 같이 보일 것 new DataProtectorTokenProvider<ApplicationUser>(dataProtectionProvider.Create("ASP.NET Identity"));
입니다.
다음과 같이 만들 수 있습니다.
Owin없이 :
[HttpGet]
[AllowAnonymous]
[Route("testReset")]
public IHttpActionResult TestReset()
{
var db = new ApplicationDbContext();
var manager = new ApplicationUserManager(new UserStore<ApplicationUser>(db));
var provider = new DpapiDataProtectionProvider("SampleAppName");
manager.UserTokenProvider = new DataProtectorTokenProvider<ApplicationUser>(
provider.Create("SampleTokenName"));
var email = "test@test.com";
var user = new ApplicationUser() { UserName = email, Email = email };
var identityUser = manager.FindByEmail(email);
if (identityUser == null)
{
manager.Create(user);
identityUser = manager.FindByEmail(email);
}
var token = manager.GeneratePasswordResetToken(identityUser.Id);
return Ok(HttpUtility.UrlEncode(token));
}
[HttpGet]
[AllowAnonymous]
[Route("testReset")]
public IHttpActionResult TestReset(string token)
{
var db = new ApplicationDbContext();
var manager = new ApplicationUserManager(new UserStore<ApplicationUser>(db));
var provider = new DpapiDataProtectionProvider("SampleAppName");
manager.UserTokenProvider = new DataProtectorTokenProvider<ApplicationUser>(
provider.Create("SampleTokenName"));
var email = "test@test.com";
var identityUser = manager.FindByEmail(email);
var valid = Task.Run(() => manager.UserTokenProvider.ValidateAsync("ResetPassword", token, manager, identityUser)).Result;
var result = manager.ResetPassword(identityUser.Id, token, "TestingTest1!");
return Ok(result);
}
Owin과 함께 :
[HttpGet]
[AllowAnonymous]
[Route("testResetWithOwin")]
public IHttpActionResult TestResetWithOwin()
{
var manager = Request.GetOwinContext().GetUserManager<ApplicationUserManager>();
var email = "test@test.com";
var user = new ApplicationUser() { UserName = email, Email = email };
var identityUser = manager.FindByEmail(email);
if (identityUser == null)
{
manager.Create(user);
identityUser = manager.FindByEmail(email);
}
var token = manager.GeneratePasswordResetToken(identityUser.Id);
return Ok(HttpUtility.UrlEncode(token));
}
[HttpGet]
[AllowAnonymous]
[Route("testResetWithOwin")]
public IHttpActionResult TestResetWithOwin(string token)
{
var manager = Request.GetOwinContext().GetUserManager<ApplicationUserManager>();
var email = "test@test.com";
var identityUser = manager.FindByEmail(email);
var valid = Task.Run(() => manager.UserTokenProvider.ValidateAsync("ResetPassword", token, manager, identityUser)).Result;
var result = manager.ResetPassword(identityUser.Id, token, "TestingTest1!");
return Ok(result);
}
그만큼 DpapiDataProtectionProvider
및 DataProtectorTokenProvider
요구 사항은 작업에 암호 재설정에 대해 동일한 이름으로 생성합니다. Owin을 사용하여 암호 재설정 토큰을 만든 다음 DpapiDataProtectionProvider
다른 이름 으로 새로 만드는 것은 작동하지 않습니다.
ASP.NET ID에 사용하는 코드 :
Web.Config :
<add key="AllowedHosts" value="example.com,example2.com" />
AccountController.cs :
[Route("RequestResetPasswordToken/{email}/")]
[HttpGet]
[AllowAnonymous]
public async Task<IHttpActionResult> GetResetPasswordToken([FromUri]string email)
{
if (!ModelState.IsValid)
return BadRequest(ModelState);
var user = await UserManager.FindByEmailAsync(email);
if (user == null)
{
Logger.Warn("Password reset token requested for non existing email");
// Don't reveal that the user does not exist
return NoContent();
}
//Prevent Host Header Attack -> Password Reset Poisoning.
//If the IIS has a binding to accept connections on 80/443 the host parameter can be changed.
//See https://security.stackexchange.com/a/170759/67046
if (!ConfigurationManager.AppSettings["AllowedHosts"].Split(',').Contains(Request.RequestUri.Host)) {
Logger.Warn($"Non allowed host detected for password reset {Request.RequestUri.Scheme}://{Request.Headers.Host}");
return BadRequest();
}
Logger.Info("Creating password reset token for user id {0}", user.Id);
var host = $"{Request.RequestUri.Scheme}://{Request.Headers.Host}";
var token = await UserManager.GeneratePasswordResetTokenAsync(user.Id);
var callbackUrl = $"{host}/resetPassword/{HttpContext.Current.Server.UrlEncode(user.Email)}/{HttpContext.Current.Server.UrlEncode(token)}";
var subject = "Client - Password reset.";
var body = "<html><body>" +
"<h2>Password reset</h2>" +
$"<p>Hi {user.FullName}, <a href=\"{callbackUrl}\"> please click this link to reset your password </a></p>" +
"</body></html>";
var message = new IdentityMessage
{
Body = body,
Destination = user.Email,
Subject = subject
};
await UserManager.EmailService.SendAsync(message);
return NoContent();
}
[HttpPost]
[Route("ResetPassword/")]
[AllowAnonymous]
public async Task<IHttpActionResult> ResetPasswordAsync(ResetPasswordRequestModel model)
{
if (!ModelState.IsValid)
return NoContent();
var user = await UserManager.FindByEmailAsync(model.Email);
if (user == null)
{
Logger.Warn("Reset password request for non existing email");
return NoContent();
}
if (!await UserManager.UserTokenProvider.ValidateAsync("ResetPassword", model.Token, UserManager, user))
{
Logger.Warn("Reset password requested with wrong token");
return NoContent();
}
var result = await UserManager.ResetPasswordAsync(user.Id, model.Token, model.NewPassword);
if (result.Succeeded)
{
Logger.Info("Creating password reset token for user id {0}", user.Id);
const string subject = "Client - Password reset success.";
var body = "<html><body>" +
"<h1>Your password for Client was reset</h1>" +
$"<p>Hi {user.FullName}!</p>" +
"<p>Your password for Client was reset. Please inform us if you did not request this change.</p>" +
"</body></html>";
var message = new IdentityMessage
{
Body = body,
Destination = user.Email,
Subject = subject
};
await UserManager.EmailService.SendAsync(message);
}
return NoContent();
}
public class ResetPasswordRequestModel
{
[Required]
[Display(Name = "Token")]
public string Token { get; set; }
[Required]
[Display(Name = "Email")]
public string Email { get; set; }
[Required]
[StringLength(100, ErrorMessage = "The {0} must be at least {2} characters long.", MinimumLength = 10)]
[DataType(DataType.Password)]
[Display(Name = "New password")]
public string NewPassword { get; set; }
[DataType(DataType.Password)]
[Display(Name = "Confirm new password")]
[Compare("NewPassword", ErrorMessage = "The new password and confirmation password do not match.")]
public string ConfirmPassword { get; set; }
}
저는 약간의 조사를했고 저에게 적합한 솔루션은이 게시물에서 발견 한 몇 가지 솔루션의 혼합이었습니다.
나는 기본적 으로이 솔루션을 컴파일하고 있으며 나를 위해 작동하는 것을 게시하고 있습니다. 제 경우에는 .net 코어의 토큰을 사용하고 싶지 않습니다.
public async Task ResetPassword(string userId, string password)
{
var user = await _userManager.FindByIdAsync(userId);
var hashPassword= _userManager.PasswordHasher.HashPassword(user, password);
user.PasswordHash = passwordHash;
await _userManager.UpdateAsync(user);
}
웹 API에 대한 Asp.Net Core Identity 사용에서 암호를 재설정하는 가장 좋은 방법입니다.
참고 * : Error () 및 Result ()는 내부 용으로 생성됩니다. 원하는대로 반환 할 수 있습니다.
[HttpPost]
[Route("reset-password")]
public async Task<IActionResult> ResetPassword(ResetPasswordModel model)
{
if (!ModelState.IsValid)
return BadRequest(ModelState);
try
{
if (model is null)
return Error("No data found!");
var user = await _userManager.FindByIdAsync(AppCommon.ToString(GetUserId()));
if (user == null)
return Error("No user found!");
Microsoft.AspNetCore.Identity.SignInResult checkOldPassword =
await _signInManager.PasswordSignInAsync(user.UserName, model.OldPassword, false, false);
if (!checkOldPassword.Succeeded)
return Error("Old password does not matched.");
string resetToken = await _userManager.GeneratePasswordResetTokenAsync(user);
if (string.IsNullOrEmpty(resetToken))
return Error("Error while generating reset token.");
var result = await _userManager.ResetPasswordAsync(user, resetToken, model.Password);
if (result.Succeeded)
return Result();
else
return Error();
}
catch (Exception ex)
{
return Error(ex);
}
}