ThreadPool.QueueUserWorkItem 的 .NET Core 替代品
.NET Core alternative to ThreadPool.QueueUserWorkItem
我正在努力实施 ForgotPassword 功能,即在 AccountController 中使用 ASP.NET 身份作为标准 VS 2015 项目模板。
我要解决的问题是,在发送密码重置邮件时,页面响应有明显的延迟。如果密码恢复尝试未找到现有帐户,则不会发送电子邮件,因此响应速度更快。所以我认为这个明显的延迟可以用于帐户枚举,即黑客可以根据忘记密码页面的响应时间来确定帐户存在。
所以我想消除页面响应时间的这种差异,这样就无法检测是否找到了帐户。
过去,我使用如下代码将可能较慢的任务排队,例如将电子邮件发送到后台线程:
ThreadPool.QueueUserWorkItem(new WaitCallback(AccountNotification.SendPasswordResetLink),
notificationInfo);
但是 ThreadPool.QueueUserWorkItem 在 .NET Core 中不存在,所以我需要一些替代方法。
我想一个想法是在 Thread.Sleep 找不到帐户的情况下引入人为延迟,但我宁愿找到一种发送电子邮件而不阻止 UI 的方法.
更新:为了澄清问题,我发布了实际代码:
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<IActionResult> ForgotPassword(ForgotPasswordViewModel model)
{
if (ModelState.IsValid)
{
var user = await userManager.FindByNameAsync(model.Email);
if (user == null || !(await userManager.IsEmailConfirmedAsync(user)))
{
// Don't reveal that the user does not exist or is not confirmed
return View("ForgotPasswordConfirmation");
}
var code = await userManager.GeneratePasswordResetTokenAsync(user);
var resetUrl = Url.Action("ResetPassword", "Account",
new { userId = user.Id, code = code },
protocol: HttpContext.Request.Scheme);
//there is a noticeable delay in the UI here because we are awaiting
await emailSender.SendPasswordResetEmailAsync(
userManager.Site,
model.Email,
"Reset Password",
resetUrl);
return View("ForgotPasswordConfirmation");
}
// If we got this far, something failed, redisplay form
return View(model);
}
是否有使用其他内置框架功能处理此问题的好方法?
只是不要等待任务。这基本上相当于 运行 开始时线程池上的所有代码,假设它不在内部等待任何东西而不调用 ConfigureAwait(false)
。 (如果这是您的代码,您需要检查一下。)
您可能想要将任务添加到服务器关闭之前应等待的某些任务集中,假设"requested shutdown"中有一些适当的概念ASP.NET。这值得研究,并且会阻止由于服务器在发送响应之后但在发送通知之前立即关闭的不幸时间而导致通知丢失。它 不会 在发送通知时出现问题的情况下提供帮助,例如您的邮件服务器已关闭。在这一点上,用户已被告知电子邮件正在发送中,在您真正保证之前......只是需要考虑的事情。
我正在努力实施 ForgotPassword 功能,即在 AccountController 中使用 ASP.NET 身份作为标准 VS 2015 项目模板。
我要解决的问题是,在发送密码重置邮件时,页面响应有明显的延迟。如果密码恢复尝试未找到现有帐户,则不会发送电子邮件,因此响应速度更快。所以我认为这个明显的延迟可以用于帐户枚举,即黑客可以根据忘记密码页面的响应时间来确定帐户存在。
所以我想消除页面响应时间的这种差异,这样就无法检测是否找到了帐户。
过去,我使用如下代码将可能较慢的任务排队,例如将电子邮件发送到后台线程:
ThreadPool.QueueUserWorkItem(new WaitCallback(AccountNotification.SendPasswordResetLink),
notificationInfo);
但是 ThreadPool.QueueUserWorkItem 在 .NET Core 中不存在,所以我需要一些替代方法。
我想一个想法是在 Thread.Sleep 找不到帐户的情况下引入人为延迟,但我宁愿找到一种发送电子邮件而不阻止 UI 的方法.
更新:为了澄清问题,我发布了实际代码:
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<IActionResult> ForgotPassword(ForgotPasswordViewModel model)
{
if (ModelState.IsValid)
{
var user = await userManager.FindByNameAsync(model.Email);
if (user == null || !(await userManager.IsEmailConfirmedAsync(user)))
{
// Don't reveal that the user does not exist or is not confirmed
return View("ForgotPasswordConfirmation");
}
var code = await userManager.GeneratePasswordResetTokenAsync(user);
var resetUrl = Url.Action("ResetPassword", "Account",
new { userId = user.Id, code = code },
protocol: HttpContext.Request.Scheme);
//there is a noticeable delay in the UI here because we are awaiting
await emailSender.SendPasswordResetEmailAsync(
userManager.Site,
model.Email,
"Reset Password",
resetUrl);
return View("ForgotPasswordConfirmation");
}
// If we got this far, something failed, redisplay form
return View(model);
}
是否有使用其他内置框架功能处理此问题的好方法?
只是不要等待任务。这基本上相当于 运行 开始时线程池上的所有代码,假设它不在内部等待任何东西而不调用 ConfigureAwait(false)
。 (如果这是您的代码,您需要检查一下。)
您可能想要将任务添加到服务器关闭之前应等待的某些任务集中,假设"requested shutdown"中有一些适当的概念ASP.NET。这值得研究,并且会阻止由于服务器在发送响应之后但在发送通知之前立即关闭的不幸时间而导致通知丢失。它 不会 在发送通知时出现问题的情况下提供帮助,例如您的邮件服务器已关闭。在这一点上,用户已被告知电子邮件正在发送中,在您真正保证之前......只是需要考虑的事情。