Microsoft is coming up with a new Membership system called ASP.NET Identity (also the default in ASP.NET MVC 5). I found the sample project, but this is not implemented a password reset.
Microsoft正在推出一个名为ASP.NET Identity的新会员系统(也是ASP.NET MVC 5中的默认系统)。我找到了示例项目,但是没有实现密码重置。
On password reset topic just found this Article: Implementing User Confirmation and Password Reset with One ASP.NET Identity – Pain or Pleasure, not help for me, because do not use the built-in password recovery.
在密码重置主题刚刚发现这篇文章:用一个ASP.NET身份实现用户确认和密码重置 - 痛苦或愉快,对我没有帮助,因为不使用内置密码恢复。
As I was looking at the options, as I think we need to generate a reset token, which I will send to the user. The user can set then the new password using the token, overwriting the old one.
当我查看选项时,我认为我们需要生成一个重置令牌,我将发送给用户。用户可以使用令牌设置新密码,覆盖旧密码。
I found the IdentityManager.Passwords.GenerateResetPasswordToken
/ IdentityManager.Passwords.GenerateResetPasswordTokenAsync(string tokenId, string userName, validUntilUtc)
, but I could not figure out what it might mean the tokenId
parameter.
我发现IdentityManager.Passwords.GenerateResetPasswordToken / IdentityManager.Passwords.GenerateResetPasswordTokenAsync(字符串tokenId,用户名字符串,validUntilUtc),但我无法找出它可能意味着tokenId参数。
How do I implement the Password Reset in ASP.NET with MVC 5.0?
如何使用MVC 5.0在ASP.NET中实现密码重置?
2 个解决方案
#1
7
I get it: The tokenid is a freely chosen identity, which identifies a password option. For example,
我明白了:tokenid是一个*选择的标识,它标识了一个密码选项。例如,
1. looks like the password recovery process, step 1 (it is based on: https://*.com/a/698879/208922)
1.看起来像密码恢复过程,第1步(它基于:https://*.com/a/698879/208922)
[HttpPost]
[ValidateAntiForgeryToken]
[AllowAnonymous]
//[RecaptchaControlMvc.CaptchaValidator]
public virtual async Task<ActionResult> ResetPassword(
ResetPasswordViewModel rpvm)
{
string message = null;
//the token is valid for one day
var until = DateTime.Now.AddDays(1);
//We find the user, as the token can not generate the e-mail address,
//but the name should be.
var db = new Context();
var user = db.Users.SingleOrDefault(x=>x.Email == rpvm.Email);
var token = new StringBuilder();
//Prepare a 10-character random text
using (RNGCryptoServiceProvider
rngCsp = new RNGCryptoServiceProvider())
{
var data = new byte[4];
for (int i = 0; i < 10; i++)
{
//filled with an array of random numbers
rngCsp.GetBytes(data);
//this is converted into a character from A to Z
var randomchar = Convert.ToChar(
//produce a random number
//between 0 and 25
BitConverter.ToUInt32(data, 0) % 26
//Convert.ToInt32('A')==65
+ 65
);
token.Append(randomchar);
}
}
//This will be the password change identifier
//that the user will be sent out
var tokenid = token.ToString();
if (null!=user)
{
//Generating a token
var result = await IdentityManager
.Passwords
.GenerateResetPasswordTokenAsync(
tokenid,
user.UserName,
until
);
if (result.Success)
{
//send the email
...
}
}
message =
"We have sent a password reset request if the email is verified.";
return RedirectToAction(
MVC.Account.ResetPasswordWithToken(
token: string.Empty,
message: message
)
);
}
2 And then when the user enters the token and the new password:
2然后当用户输入令牌和新密码时:
[HttpPost]
[ValidateAntiForgeryToken]
[AllowAnonymous]
//[RecaptchaControlMvc.CaptchaValidator]
public virtual async Task<ActionResult> ResetPasswordWithToken(
ResetPasswordWithTokenViewModel
rpwtvm
)
{
if (ModelState.IsValid)
{
string message = null;
//reset the password
var result = await IdentityManager.Passwords.ResetPasswordAsync(
rpwtvm.Token,
rpwtvm.Password
);
if (result.Success)
{
message = "the password has been reset.";
return RedirectToAction(
MVC.Account.ResetPasswordCompleted(message: message)
);
}
else
{
AddErrors(result);
}
}
return View(MVC.Account.ResetPasswordWithToken(rpwtvm));
}
Skeleton proposal to sample project on github, if anyone needs it may be tested.The E-mail sending not yet written, possibly with the addition soon.
在github上对项目进行示例的骷髅提议,如果有人需要它可能会被测试。电子邮件发送尚未写入,可能很快就会添加。
#2
5
Seems like a lot of trouble... What advantage does the above give over:
好像很麻烦......上面给出了什么优势:
- the user clicking a 'Recover Account' link
- 用户点击“恢复帐户”链接
- this sends an 64 byte encoded string of a datetime ticks value (call it psuedo-hash) in an email
- 这会在电子邮件中发送64字节编码的日期时间刻度值(称为psuedo-hash)
- click the link back in the email to a controller/action route that
- 单击电子邮件中的链接返回到控制器/操作路径
- matches email and it's source server to psuedo-hash, decrypts the psuedo-hash, validates the time since sent and
- 将电子邮件和它的源服务器匹配到psuedo-hash,解密psuedo-hash,验证自发送后的时间和
- offers a View for the user to set a new password
- 为用户提供了一个用于设置新密码的视图
- with a valid password, the code removes the old user password and assigns the new.
- 使用有效密码,代码将删除旧用户密码并分配新密码。
- Once complete, successful or not, delete the psuedo-hash.
- 一旦完成,成功与否,删除psuedo-hash。
With this flow, at no time do you EVER send a password out of your domain.
有了这个流程,您在任何时候都不会从您的域名中发送密码。
Please, anyone, prove to me how this is any less secure.
请任何人向我证明这是不安全的。
#1
7
I get it: The tokenid is a freely chosen identity, which identifies a password option. For example,
我明白了:tokenid是一个*选择的标识,它标识了一个密码选项。例如,
1. looks like the password recovery process, step 1 (it is based on: https://*.com/a/698879/208922)
1.看起来像密码恢复过程,第1步(它基于:https://*.com/a/698879/208922)
[HttpPost]
[ValidateAntiForgeryToken]
[AllowAnonymous]
//[RecaptchaControlMvc.CaptchaValidator]
public virtual async Task<ActionResult> ResetPassword(
ResetPasswordViewModel rpvm)
{
string message = null;
//the token is valid for one day
var until = DateTime.Now.AddDays(1);
//We find the user, as the token can not generate the e-mail address,
//but the name should be.
var db = new Context();
var user = db.Users.SingleOrDefault(x=>x.Email == rpvm.Email);
var token = new StringBuilder();
//Prepare a 10-character random text
using (RNGCryptoServiceProvider
rngCsp = new RNGCryptoServiceProvider())
{
var data = new byte[4];
for (int i = 0; i < 10; i++)
{
//filled with an array of random numbers
rngCsp.GetBytes(data);
//this is converted into a character from A to Z
var randomchar = Convert.ToChar(
//produce a random number
//between 0 and 25
BitConverter.ToUInt32(data, 0) % 26
//Convert.ToInt32('A')==65
+ 65
);
token.Append(randomchar);
}
}
//This will be the password change identifier
//that the user will be sent out
var tokenid = token.ToString();
if (null!=user)
{
//Generating a token
var result = await IdentityManager
.Passwords
.GenerateResetPasswordTokenAsync(
tokenid,
user.UserName,
until
);
if (result.Success)
{
//send the email
...
}
}
message =
"We have sent a password reset request if the email is verified.";
return RedirectToAction(
MVC.Account.ResetPasswordWithToken(
token: string.Empty,
message: message
)
);
}
2 And then when the user enters the token and the new password:
2然后当用户输入令牌和新密码时:
[HttpPost]
[ValidateAntiForgeryToken]
[AllowAnonymous]
//[RecaptchaControlMvc.CaptchaValidator]
public virtual async Task<ActionResult> ResetPasswordWithToken(
ResetPasswordWithTokenViewModel
rpwtvm
)
{
if (ModelState.IsValid)
{
string message = null;
//reset the password
var result = await IdentityManager.Passwords.ResetPasswordAsync(
rpwtvm.Token,
rpwtvm.Password
);
if (result.Success)
{
message = "the password has been reset.";
return RedirectToAction(
MVC.Account.ResetPasswordCompleted(message: message)
);
}
else
{
AddErrors(result);
}
}
return View(MVC.Account.ResetPasswordWithToken(rpwtvm));
}
Skeleton proposal to sample project on github, if anyone needs it may be tested.The E-mail sending not yet written, possibly with the addition soon.
在github上对项目进行示例的骷髅提议,如果有人需要它可能会被测试。电子邮件发送尚未写入,可能很快就会添加。
#2
5
Seems like a lot of trouble... What advantage does the above give over:
好像很麻烦......上面给出了什么优势:
- the user clicking a 'Recover Account' link
- 用户点击“恢复帐户”链接
- this sends an 64 byte encoded string of a datetime ticks value (call it psuedo-hash) in an email
- 这会在电子邮件中发送64字节编码的日期时间刻度值(称为psuedo-hash)
- click the link back in the email to a controller/action route that
- 单击电子邮件中的链接返回到控制器/操作路径
- matches email and it's source server to psuedo-hash, decrypts the psuedo-hash, validates the time since sent and
- 将电子邮件和它的源服务器匹配到psuedo-hash,解密psuedo-hash,验证自发送后的时间和
- offers a View for the user to set a new password
- 为用户提供了一个用于设置新密码的视图
- with a valid password, the code removes the old user password and assigns the new.
- 使用有效密码,代码将删除旧用户密码并分配新密码。
- Once complete, successful or not, delete the psuedo-hash.
- 一旦完成,成功与否,删除psuedo-hash。
With this flow, at no time do you EVER send a password out of your domain.
有了这个流程,您在任何时候都不会从您的域名中发送密码。
Please, anyone, prove to me how this is any less secure.
请任何人向我证明这是不安全的。