ASP.NET पहचान रीसेट पासवर्ड


95

मुझे नए ASP.NET पहचान प्रणाली में उपयोगकर्ता का पासवर्ड कैसे मिल सकता है? या मैं मौजूदा एक (उपयोगकर्ता पासवर्ड भूल गया) को जाने बिना कैसे रीसेट कर सकता हूं?

जवाबों:


102

वर्तमान रिलीज में

यह मानकर कि आप भूल गए पासवर्ड को रीसेट करने के लिए अनुरोध के सत्यापन को संभाल चुके हैं, नमूना कोड चरणों के रूप में निम्नलिखित कोड का उपयोग करें।

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 नाइटली बिल्ड में

फोर्गेसपासवर्ड जैसे अनुरोधों को संभालने के लिए टोकन के साथ काम करने के लिए फ्रेमवर्क अपडेट किया गया है। रिलीज़ होने के बाद, सरल कोड मार्गदर्शन अपेक्षित है।

अपडेट करें:

यह अपडेट केवल अधिक स्पष्ट चरण प्रदान करने के लिए है।

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);

क्या आप जानते हैं कि संस्करण 1.1 कब जारी किया जाएगा?
ग्रेक्रो

अल्फा में अभी भी है, और 1.0 अभी जारी है। इसलिए कई महीने मान लेते हैं। myget.org/gallery/aspnetwebstacknightly
jd4u

11
अजीब तरह से स्टोर ।etPasswordHashAsync (cUser, hashedNewPassword) मेथड कॉल ने मेरे लिए काम नहीं किया, इसके बजाय मुझे मैन्युअल रूप से cUser.PasswordHash = hashedNewPassword सेट करना पड़ा और फिर UserManager.UpdateAsync (उपयोगकर्ता) को कॉल करें;
एंडी मेहलिक

1
यदि उपयोगकर्ता पुनर्प्राप्ति संदर्भ और स्टोर संदर्भ भिन्न हैं, तो कोड केवल काम करना संभव नहीं है। कोड केवल एक नमूना चरण था, सटीक नहीं। जल्द ही दूसरों के लिए इस मुद्दे से बचने के लिए जवाब अपडेट करेंगे।
jd4u

1
फ्रेमवर्क 1 प्रदान नहीं करता है। लेकिन फ्रेमवर्क 2-अल्फा में कुछ विशेषताएं हैं जो पासवर्ड रीसेट अनुरोधों को संभालने के लिए सरल प्रक्रिया प्रदान कर सकती हैं। aspnetidentity.codeplex.com
jd4u

138

या मैं मौजूदा एक (उपयोगकर्ता पासवर्ड भूल गया) को जाने बिना कैसे रीसेट कर सकता हूं?

यदि आप UserManager का उपयोग करके पासवर्ड बदलना चाहते हैं, लेकिन आप उपयोगकर्ता के वर्तमान पासवर्ड की आपूर्ति नहीं करना चाहते हैं, तो आप पासवर्ड रीसेट टोकन उत्पन्न कर सकते हैं और फिर इसके बजाय तुरंत इसका उपयोग कर सकते हैं।

string resetToken = await UserManager.GeneratePasswordResetTokenAsync(model.Id);
IdentityResult passwordChangeResult = await UserManager.ResetPasswordAsync(model.Id, resetToken, model.NewPassword);

8
यह एक नया पासवर्ड सेट करने का सबसे अच्छा और साफ तरीका है। स्वीकृत उत्तर के साथ समस्या यह है कि यह पासवर्ड हैशर को सीधे एक्सेस करके पासवर्ड की जटिलता मान्यताओं को दरकिनार कर देता है।
क्रिस

6
Fyi, आपको त्रुटि मिल सकती है 'No IUserTokenProvider पंजीकृत है।' यदि आपको तर्क से ऊपर का उपयोग मिलता है। इसे देखें stackoverflow.com/questions/22629936/…
प्रसाद कानापर्थी

1
यह Microsoft.AspNet.Identity के लिए केवल 2 संस्करण में काम करता है, मुझे लगता है। आप संस्करण 1 में GeneratePasswordResetTokenAsync विधि नहीं ढूँढ सकते हैं
romanoza

आपके उत्तर के लिए धन्यवाद। यह मेरे लिए एक आकर्षण की तरह काम करता है।
थॉमस .बेंग्

4
यदि आपको अमान्य टोकन मिलता है , तो सुनिश्चित करें कि SecurityStampआपके उपयोगकर्ता के लिए अशक्त नहीं है। यह उन उपयोगकर्ताओं के लिए हो सकता है जो अन्य डेटाबेस से चले गए हैं, या वे उपयोगकर्ता जो UserManager.CreateAsync()विधि के माध्यम से नहीं बनाए गए थे ।
एलिसन

70

पदावनत

यह मूल उत्तर था। यह काम करता है, लेकिन एक समस्या है। क्या होगा अगर 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

अब सिफारिश की है

एडवर्डब्रे ने जो उत्तर प्रस्तावित किया और उसके बाद डैनियलवर्थ ने बाद में एक कोड नमूने के साथ विस्तृत रूप से उपयोग करना बेहतर समझा


1
इसके लिए भगवान का शुक्र है, मैंने सोचा कि जब तक मैंने यह नहीं देखा, मुझे एक नया उपयोगकर्ता स्टोर बनाना होगा!
ल्यूक

वहाँ सीधे SQL में ऐसा करने का कोई तरीका है? मैं एक निष्पादन योग्य के बजाय जरूरत पड़ने पर अपने डीबीए को कॉल करने के लिए एक स्पार्क हाथ लगाना चाहूंगा।
मार्क रिचमैन

@ मर्करिचमैन यह एक नया प्रश्न है। हालाँकि, एक चीज़ जो आप कर सकते हैं, वह है SQL सर्वर पर चलने वाले T-SQL का निरीक्षण करना।
शॉन लुटिन

3
इसके साथ देखें, जब भी AddPassword विफल होता है (अर्थात अपर्याप्त पासवर्ड जटिलता), उपयोगकर्ता को पासवर्ड के बिना छोड़ दिया जाएगा।
क्रिस

1
अच्छी तरह से किसी भी व्यावसायिक नियमों को दरकिनार किए बिना सबसे साफ दृष्टिकोण (क्योंकि जब आप सीधे पासवर्ड हैशर का उपयोग करते हैं तो कोई पासवर्ड जटिलता सत्यापन नहीं है) जो डैनियल राइट ने प्रस्तावित किया है।
क्रिस

29

अपने पर UserManager, पहले GeneratePasswordResetTokenAsync पर कॉल करें । उपयोगकर्ता द्वारा अपनी पहचान सत्यापित करने के बाद (उदाहरण के लिए ईमेल में टोकन प्राप्त करने के लिए), टोकन को ResetPasswordAsync पर पास करें ।


1
ResetPasswordAsync को उपयोगकर्ता आईडी की आवश्यकता क्यों है, यह जानने की कोशिश की जा रही है और टोकन के साथ दिखाने पर उपयोगकर्ता से इसे प्राप्त करने का एक उचित तरीका है। GeneratePasswordReset एक टोकन का उपयोग करता है जो 150 से अधिक वर्णों का होता है ... ऐसा लगता है कि यह एक उपयोगकर्ता आईडी को क्रिप्टोग्राफिक रूप से स्टोव करने के लिए पर्याप्त होगा, इसलिए मुझे खुद को लागू करने की आवश्यकता नहीं है। :(
पेटीस

मुझे लगता है कि यह उपयोगकर्ता आईडी के लिए पूछ रहा है, इसलिए यह उस उपयोगकर्ता आईडी के खिलाफ पहचान डेटाबेस में रीसेट टोकन दर्ज कर सकता है। यदि यह ऐसा नहीं करता है तो फ्रेमवर्क को कैसे पता चलेगा कि टोकन वैध था। आपको User.Identity.GetUserId () या समान का उपयोग करके उपयोगकर्ता आईडी खींचने में सक्षम होना चाहिए।
रयान बुद्धिकोम

1
उपयोगकर्ता आईडी की आवश्यकता एपीआई के हिस्से पर एक मूर्खतापूर्ण विकल्प है, टोकन डेटाबेस में पहले से ही है जब ResetPassword (async) कहा जाता है और यह इनपुट के खिलाफ इसे सत्यापित करने के लिए पर्याप्त होना चाहिए।
फिलिप

@ फ़ीलिप, ResetPasswordAsyncएक उपयोगकर्ता आईडी लेने का लाभ यह है कि पहचान प्रदाता को केवल उपयोगकर्ता आईडी को इंडेक्स करने की आवश्यकता होती है, टोकन भी नहीं। यदि कई उपयोगकर्ता हैं तो यह बेहतर पैमाने देता है।
एडवर्ड ब्रे जूल

1
@ एडवर्ड ब्रे, आप रीसेट कॉल के लिए उपयोगकर्ता आईडी कैसे लाते हैं?
फ़िलिप

2
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);
}

कोड का यह स्निपेट जीथब पर उपलब्ध AspNetIdentitySample परियोजना से लिया गया है


2

में विधि बनाएँ 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);
}

2

वेब एपीआई के लिए Asp.Net कोर आइडेंटिटी में पासवर्ड रीसेट करने का सबसे अच्छा तरीका।

नोट * : त्रुटि () और परिणाम () आंतरिक उपयोग के लिए बनाए गए हैं। तुम चाहो तो लौट सकते हो।

        [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);
            }
        }

2
यह मेरे लिए Fx v 4.5 के साथ भी काम किया। दूसरे उपाय से काम नहीं चला। मौलिक रूप से यह बहुत सरल था। आपको वास्तव में उपयोगकर्ता प्राप्त करने की आवश्यकता नहीं है क्योंकि सभी विधियां आईडी को स्वीकार करेंगी। मुझे बस अपने व्यवस्थापक इंटरफ़ेस में एक अस्थायी एक-बंद रीसेट के लिए इसकी आवश्यकता थी, इसलिए मुझे सभी त्रुटि जांचों की आवश्यकता नहीं थी।
स्टीव हेनर

1

पासवर्ड रीसेट के मामले में, इसे पंजीकृत उपयोगकर्ता ईमेल पर पासवर्ड रीसेट टोकन भेजने के माध्यम से रीसेट करने की सलाह दी जाती है और उपयोगकर्ता को नया पासवर्ड प्रदान करने के लिए कहा जाता है। यदि डिफ़ॉल्ट कॉन्फ़िगरेशन बसने के साथ पहचान फ्रेमवर्क पर आसानी से उपयोग करने योग्य .NET लाइब्रेरी बनाई है। आप ब्लॉग लिंक और जीथब पर स्रोत कोड में विवरण पा सकते हैं ।


1

मुझे लगता है कि ASP.NET पहचान के लिए Microsoft गाइड एक अच्छी शुरुआत है।

https://docs.microsoft.com/en-us/aspnet/identity/overview/features-api/account-confirmation-and-password-recovery-with-aspnet-identity

ध्यान दें:

यदि आप AccountController का उपयोग नहीं करते हैं और अपना पासवर्ड रीसेट करने के लिए उपयोग नहीं करते हैं, तो उपयोग करें Request.GetOwinContext().GetUserManager<ApplicationUserManager>();। यदि आपके पास एक ही OwinContext नहीं है, तो आपको DataProtectorTokenProviderएक OwinContextउपयोग की तरह एक नया बनाने की आवश्यकता है । डिफ़ॉल्ट रूप से देखें App_Start -> IdentityConfig.cs। कुछ ऐसा दिखना चाहिए new DataProtectorTokenProvider<ApplicationUser>(dataProtectionProvider.Create("ASP.NET Identity"));

इस तरह बनाया जा सकता है:

स्वामी के बिना:

[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);
}

ओविन के साथ:

[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जरूरतों को काम करने के लिए एक पासवर्ड रीसेट के लिए एक ही नाम के साथ बनाया जा करने के लिए। पासवर्ड रीसेट टोकन बनाने के लिए ओविन का उपयोग करना और फिर एक DpapiDataProtectionProviderअन्य नाम के साथ एक नया बनाना काम नहीं करेगा।

कोड जो मैं ASP.NET पहचान के लिए उपयोग करता हूं:

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; }
}

1

मैंने थोड़ी जांच की और जो समाधान मेरे लिए काम करता है वह इस पोस्ट में स्थापित कुछ समाधानों का मिश्रण था।

मैं मूल रूप से इस समाधान का संकलन कर रहा हूं और मैं पोस्ट कर रहा हूं कि मेरे लिए क्या काम करता है। मेरे मामले में, मैं .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);

}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.