Yeni ASP.NET Identity sisteminde bir kullanıcının parolasını nasıl alabilirim? Veya mevcut olanı bilmeden nasıl sıfırlayabilirim (kullanıcı şifreyi unuttu)?
Yanıtlar:
Mevcut sürümde
Unutulan şifreyi sıfırlama talebinin doğrulanmasını gerçekleştirdiğinizi varsayarak, aşağıdaki kodu örnek kod adımları olarak kullanın.
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'ta
Çerçeve, ForgetPassword gibi istekleri işlemek için Token ile çalışacak şekilde güncellenmiştir. Yayınlandıktan sonra, basit bir kod kılavuzu beklenmektedir.
Güncelleme:
Bu güncelleme sadece daha net adımlar sağlamak içindir.
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);
Veya mevcut olanı bilmeden nasıl sıfırlayabilirim (kullanıcı şifreyi unuttu)?
UserManager'ı kullanarak bir parolayı değiştirmek istiyorsanız, ancak kullanıcının geçerli parolasını sağlamak istemiyorsanız, bir parola sıfırlama belirteci oluşturabilir ve bunun yerine hemen kullanabilirsiniz.
string resetToken = await UserManager.GeneratePasswordResetTokenAsync(model.Id);
IdentityResult passwordChangeResult = await UserManager.ResetPasswordAsync(model.Id, resetToken, model.NewPassword);
SecurityStamp
, kullanıcınız için boş olmadığından emin olun . Bu, diğer veritabanlarından taşınan kullanıcılar veya UserManager.CreateAsync()
yöntemle oluşturulmamış kullanıcılar için olabilir .
Orijinal cevap buydu. Çalışıyor ama bir sorunu var. FarzedelimAddPassword
başarısız olursa? Kullanıcı şifresiz bırakılır.
Orijinal cevap: Üç satır kod kullanabiliriz:
UserManager<IdentityUser> userManager =
new UserManager<IdentityUser>(new UserStore<IdentityUser>());
userManager.RemovePassword(userId);
userManager.AddPassword(userId, newPassword);
Ayrıca bakınız: http://msdn.microsoft.com/en-us/library/dn457095(v=vs.111).aspx
EdwardBrey'in önerdiği cevabı kullanmak muhtemelen daha iyidir ve daha sonra DanielWright daha sonra bir kod örneği ile detaylandırmıştır .
Senin üzerinde UserManager
, ilk çağrı GeneratePasswordResetTokenAsync . Kullanıcı kimliğini doğruladıktan sonra (örneğin belirteci bir e-postada alarak), belirteci ResetPasswordAsync'e iletin .
ResetPasswordAsync
bir kullanıcı kimliği almanın avantajı , kimlik sağlayıcının jetonları değil, yalnızca kullanıcı kimliklerini endekslemesi gerektiğidir. Bu, çok sayıda kullanıcı varsa daha iyi ölçeklenmesini sağlar.
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);
}
Bu kod parçası, github'da bulunan AspNetIdentitySample projesinden çıkarılmıştır .
İçinde yöntem oluştur 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);
}
Web API için Asp.Net Core Identity'de Parola Sıfırlamanın en iyi yolu.
Not * : Hata () ve Sonuç () dahili kullanım için oluşturulmuştur. İstediğin zaman geri dönebilirsin.
[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);
}
}
Şifre sıfırlama durumunda, kayıtlı kullanıcı e-postasına şifre sıfırlama belirteci gönderilerek sıfırlanması ve kullanıcıdan yeni şifre girmesini istemeniz önerilir. Varsayılan yapılandırma ayarları ile Identity çerçevesi üzerinden kolayca kullanılabilen bir .NET kitaplığı oluşturduysanız. Ayrıntıları blog bağlantısında ve kaynak kodunu github'da bulabilirsiniz.
ASP.NET Identity için Microsoft kılavuzunun iyi bir başlangıç olduğunu düşünüyorum.
Not:
AccountController kullanmıyorsanız ve şifrenizi sıfırlamak istemiyorsanız, kullanın Request.GetOwinContext().GetUserManager<ApplicationUserManager>();
. Aynı OwinContext'e sahip değilseniz DataProtectorTokenProvider
, OwinContext
kullandığı gibi yeni bir tane oluşturmanız gerekir . Varsayılan olarak bakın App_Start -> IdentityConfig.cs
. Bir şeye benzemelinew DataProtectorTokenProvider<ApplicationUser>(dataProtectionProvider.Create("ASP.NET Identity"));
.
Şu şekilde oluşturulabilir:
Owin olmadan:
[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 ile:
[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
Ve DataProtectorTokenProvider
ihtiyaçlar çalışmalarına bir şifre sıfırlama için aynı isimde oluşturulacak. Parola sıfırlama belirteci oluşturmak için Owin'i kullanma ve ardından yeni birDpapiDataProtectionProvider
başka bir adla işe yaramaz.
ASP.NET Identity için kullandığım kod:
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; }
}
Biraz araştırma yaptım ve benim için işe yarayan çözüm, bu yazıda kurulan birkaç çözümün bir karışımıydı.
Temelde bu çözümü derliyorum ve benim için neyin işe yaradığını yayınlıyorum. Benim durumumda, .net çekirdeğinden herhangi bir belirteç kullanmak istemiyorum.
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);
}