目录
介绍
使用代码
先决条件
步骤1——将UnconfirmedEmail属性添加到IdentityUser
第2步——更新数据库
第3步——添加更改电子邮件页面
第4步——修改配置文件
第5步——重写UserManager
在新的ASP.NET Core 2.2 Razor页面模板中支持并修改Identity
- 下载源代码 - 931.3 KB
ASP.NET Core 2.2 Web应用程序2部分中的第2部分,允许用户更新已确认的电子邮件。以下是允许用户更新其电子邮件的步骤。
要求在ASP.NET Core 2.2中确认电子邮件——第1部分
使用代码 先决条件- .NET Core 2.2 SDK
- 以下VS中的一个:
- Visual Studio版本2017年15.9或更高版本
- Visual Studio for Mac 7.7或更高版本
- Visual Studio Code C#扩展版本1.17.1或更高版本
您可以在完成第1部分中的步骤后下载VS 2017项目或按照以下步骤修改您自己的项目。
步骤1——将UnconfirmedEmail属性添加到IdentityUser在Entities文件夹中添加命名为ApplicationUser的新类:
using Microsoft.AspNetCore.Identity;
namespace .Entities
{
public class ApplicationUser : IdentityUser
{
[PersonalData]
public string UnconfirmedEmail { get; set; }
}
}
使用查找和替换,以当前工程中替换为。
使用ApplicationUser编辑Startup.cs > ConfigureServices:
services.AddIdentity
编辑Areas\Identity\Pages\Account\Manage\EnableAuthenticator.cshtml.cs:
private async Task LoadSharedKeyAndQrCodeUriAsync(ApplicationUser user)
编辑Areas\Identity\Pages\Account\Manage\DownloadPersonalData.cshtml.cs:
var personalDataProps = typeof(ApplicationUser).GetProperties().Where(
prop => Attribute.IsDefined(prop, typeof(PersonalDataAttribute)));
编辑Areas\Identity\Pages\Account\ExternalLogin.cshtml.cs:
var user = new ApplicationUser { UserName = Input.Email, Email = Input.Email };
编辑Register.cshtml.cs:
var user = new ApplicationUser { UserName = Input.UserName, Email = Input.Email };
解决替换IdentityUser的命名空间问题。
using .Entities;
或者用于cshtml:
@using .Entities;
构建项目并检查错误。
第2步——更新数据库编辑在Data文件夹中的ApplicationDbContext,添加ApplicationUser:
public class ApplicationDbContext : IdentityDbContext
从VS 2017中的程序包管理器控制台运行命令“ Add-Migration UnconfirmedEmail ”。
运行命令“ Update-Database”。
第3步——添加更改电子邮件页面编辑ManageNavPages.cs,在上面添加ChangePassword属性:
public static string ChangeEmail => "ChangeEmail";
和:
public static string ChangeEmailNavClass(ViewContext viewContext) =>
PageNavClass(viewContext, ChangeEmail);
编辑_ManageNav.cshtml,在下面添加个人资料项:
Email
在Areas\Identity\Pages\Account\Manage中创建名为ChangeEmail的razer页面。
编辑ChangeEmail.cshtml:
@page
@model ChangeEmailModel
@{
ViewData["Title"] = "Change Email";
ViewData["ActivePage"] = ManageNavPages.ChangeEmail;
}
@ViewData["Title"]
New email needs to be verified.
Update Email
@section Scripts {
}
编辑ChangeEmail.cshtml.cs:
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Text.Encodings.Web;
using System.Threading.Tasks;
using .Services;
using .Entities;
namespace .Areas.Identity.Pages.Account.Manage
{
public class ChangeEmailModel : PageModel
{
private readonly UserManager _userManager;
private readonly SignInManager _signInManager;
private readonly ILogger _logger;
private readonly IEmailSender _emailSender;
public ChangeEmailModel(
UserManager userManager,
SignInManager signInManager,
ILogger logger,
IEmailSender emailSender)
{
_userManager = userManager;
_signInManager = signInManager;
_logger = logger;
_emailSender = emailSender;
}
[BindProperty]
public InputModel Input { get; set; }
[TempData]
[Display(Name = "Verified Email")]
public string Email { get; set; }
[TempData]
public string StatusMessage { get; set; }
public class InputModel
{
[Required]
[EmailAddress]
[Display(Name = "New Email")]
public string Email { get; set; }
}
public async Task OnGetAsync()
{
var user = await _userManager.GetUserAsync(User);
if (user == null)
{
return NotFound($"Unable to load user with ID '{_userManager.GetUserId(User)}'.");
}
var email = await _userManager.GetEmailAsync(user);
Email = email;
return Page();
}
public async Task OnPostAsync()
{
if (!ModelState.IsValid)
{
return Page();
}
var user = await _userManager.GetUserAsync(User);
if (user == null)
{
return NotFound($"Unable to load user with ID '{_userManager.GetUserId(User)}'.");
}
var email = await _userManager.GetEmailAsync(user);
if (Input.Email != email)
{
var errors = new List();
if (_userManager.Options.User.RequireUniqueEmail)
{
var owner = await _userManager.FindByEmailAsync(Input.Email);
if (owner != null && !string.Equals
(await _userManager.GetUserIdAsync(owner),
await _userManager.GetUserIdAsync(user)))
{
ModelState.AddModelError(string.Empty,
new IdentityErrorDescriber().DuplicateEmail(Input.Email).Description);
return Page();
}
}
var setEmailResult = await _userManager.SetEmailAsync(user, Input.Email);
if (!setEmailResult.Succeeded)
{
var userId = await _userManager.GetUserIdAsync(user);
throw new InvalidOperationException($"Unexpected error occurred
setting email for user with ID '{userId}'.");
}
if (Input.Email.ToUpper() != email.ToUpper())
{
var result = await _userManager.UpdateSecurityStampAsync(user);
if (!result.Succeeded)
{
foreach (var error in result.Errors)
{
ModelState.AddModelError(string.Empty, error.Description);
return Page();
}
}
var code = await _userManager.GenerateEmailConfirmationTokenAsync(user);
var callbackUrl = Url.Page(
"/Account/ConfirmEmail",
pageHandler: null,
values: new { userId = user.Id, code = code },
protocol: Request.Scheme);
await _emailSender.SendEmailAsync(Input.Email, "Confirm your email",
$"Please confirm your account by
clicking here.");
_logger.LogInformation("User updated their UnconfirmedEmail.");
StatusMessage = "Please check your inbox to confirm the new email.";
}
else
{
_logger.LogInformation("User updated their Email.");
StatusMessage = "Your email has been updated.";
}
}
return RedirectToPage();
}
}
}
第4步——修改配置文件
在Areas\Identity\Pages\Account\Manage中编辑Index.cshtml.cs使用新的ChangeEmail页面。
添加:
public string Email { get; set; }
去掉:
public bool IsEmailConfirmed { get; set; }
从InputModel中删除:
[Required]
[EmailAddress]
public string Email { get; set; }
从OnGetAsync>Input中删除:
Email = email,
从OnGetAsync中删除:
IsEmailConfirmed = await _userManager.IsEmailConfirmedAsync(user);
从OnPostAsync中删除:
var email = await _userManager.GetEmailAsync(user);
if (Input.Email != email)
{
var setEmailResult = await _userManager.SetEmailAsync(user, Input.Email);
if (!setEmailResult.Succeeded)
{
var userId = await _userManager.GetUserIdAsync(user);
throw new InvalidOperationException($"Unexpected error occurred
setting email for user with ID '{userId}'.");
}
}
删除:
public async Task OnPostSendVerificationEmailAsync()
{
if (!ModelState.IsValid)
{
return Page();
}
var user = await _userManager.GetUserAsync(User);
if (user == null)
{
return NotFound($"Unable to load user with ID '
{_userManager.GetUserId(User)}'.");
}
var userId = await _userManager.GetUserIdAsync(user);
var email = await _userManager.GetEmailAsync(user);
var code = await _userManager.GenerateEmailConfirmationTokenAsync(user);
var callbackUrl = Url.Page(
"/Account/ConfirmEmail",
pageHandler: null,
values: new { userId = userId, code = code },
protocol: Request.Scheme);
await _emailSender.SendEmailAsync(
email,
"Confirm your email",
$"Please confirm your account by clicking here.");
StatusMessage = "Verification email sent. Please check your email.";
return RedirectToPage();
}
编辑Index.cshtml。
更换:
@if (Model.IsEmailConfirmed)
{
}
else
{
Send verification email
}
使用:
第5步——重写UserManager
在Services文件夹中添加命名为ApplicationUserManager的新类:
using Microsoft.AspNetCore.Identity;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using .Entities;
namespace .Services
{
public class ApplicationUserManager : UserManager
{
public ApplicationUserManager(IUserStore store,
IOptions optionsAccessor,
IPasswordHasher passwordHasher,
IEnumerable userValidators,
IEnumerable passwordValidators,
ILookupNormalizer keyNormalizer,
IdentityErrorDescriber errors,
IServiceProvider services,
ILogger logger)
: base(store, optionsAccessor, passwordHasher, userValidators,
passwordValidators, keyNormalizer, errors, services, logger)
{
}
///
/// Sets the address for a .
///
/// The user whose email should be set.
/// The email to set.
///
/// The that represents the asynchronous operation,
/// containing the
/// of the operation.
///
public override async Task SetEmailAsync(ApplicationUser user, string email)
{
ThrowIfDisposed();
if (user == null)
{
throw new ArgumentNullException(nameof(user));
}
if (user.EmailConfirmed && user.Email.ToUpper() != email.ToUpper())
user.UnconfirmedEmail = email;
else
user.Email = email;
return await UpdateUserAsync(user);
}
///
/// Validates that an email confirmation token matches the specified
/// and if successful sets
/// EmailConfirmed to true and if UnconfirmedEmail is not NULL or Empty,
/// copies the user's UnconfirmedEmail to user's
/// Email and sets UnconfirmedEmail to NULL.
///
/// The user to validate the token against.
/// The email confirmation token to validate.
///
/// The that represents the asynchronous operation,
/// containing the
/// of the operation.
///
public override async Task
ConfirmEmailAsync(ApplicationUser user, string token)
{
ThrowIfDisposed();
if (user == null)
{
throw new ArgumentNullException(nameof(user));
}
IdentityResult result;
var provider = Options.Tokens.EmailConfirmationTokenProvider;
var isValidToken = await base.VerifyUserTokenAsync
(user, provider, "EmailConfirmation", token);
if (isValidToken)
{
if (!string.IsNullOrEmpty(user.UnconfirmedEmail))
{
user.Email = user.UnconfirmedEmail;
user.UnconfirmedEmail = null;
}
user.EmailConfirmed = true;
result = await UpdateUserAsync(user);
}
else
{
result = IdentityResult.Failed(new IdentityErrorDescriber().InvalidToken());
}
return result;
}
}
}
编辑Startup.cs > ConfigureServices,添加.AddUserManager():
services.AddIdentity(config =>
{
config.SignIn.RequireConfirmedEmail = true;
config.User.RequireUniqueEmail = true;
})
.AddDefaultUI(UIFramework.Bootstrap4)
.AddEntityFrameworkStores()
.AddUserManager()
.AddDefaultTokenProviders();
构建并测试项目。
原文地址:https://www.codeproject.com/Articles/1272510/Require-Confirmed-Email-in-ASP-NET-Core-2-2-Part-2