Кто-нибудь знает, как включить пользователя для изменения имени пользователя/электронной почты с идентификатором ASP.NET с подтверждением электронной почты? Есть много примеров того, как изменить пароль, но я ничего не могу найти по этому поводу.
Ответ 2
Trailmax получил большую часть этого права, но, как отмечали в комментариях, пользователь будет по существу чередоваться, если они будут испортить свой новый адрес электронной почты при обновлении.
Чтобы решить эту проблему, необходимо добавить дополнительные свойства в свой пользовательский класс и изменить логин. (Примечание: этот ответ будет адресован ему через проект MVC 5)
Здесь, где я взял его:
1. Измените объект пользователя
Во-первых, позвольте обновить пользователя приложения, чтобы добавить дополнительное поле, которое нам понадобится. Вы добавите это в файл IdentiyModel.cs в папке "Модели":
public class ApplicationUser : IdentityUser
{
public async Task<ClaimsIdentity> GenerateUserIdentityAsync(UserManager<ApplicationUser> manager)
{
// Note the authenticationType must match the one defined in CookieAuthenticationOptions.AuthenticationType
var userIdentity = await manager.CreateIdentityAsync(this, DefaultAuthenticationTypes.ApplicationCookie);
// Add custom user claims here
return userIdentity;
}
[MaxLength(256)]
public string UnConfirmedEmail { get; set; }//this is what we add
}
Если вы хотите увидеть более подробный пример этого, посмотрите здесь http://blog.falafel.com/customize-mvc-5-application-users-using-asp-net-identity-2-0/ (это пример я используется)
Кроме того, он не упоминает об этом в связанной статье, но вы также захотите обновить таблицу AspNetUsers:
ALTER TABLE dbo.AspNetUsers
ADD [UnConfirmedEmail] NVARCHAR(256) NULL;
2. Обновите свой логин
Теперь нам нужно убедиться, что наш логин проверяет прежнее подтверждение по электронной почте, так что все может быть "в неопределенности", пока мы ждем, когда пользователь подтвердит это новое электронное письмо:
//
// POST: /Account/Login
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Login(LoginViewModel model, string returnUrl)
{
if (!ModelState.IsValid)
{
return View(model);
}
var allowPassOnEmailVerfication = false;
var user = await UserManager.FindByEmailAsync(model.Email);
if (user != null)
{
if (!string.IsNullOrWhiteSpace(user.UnConfirmedEmail))
{
allowPassOnEmailVerfication = true;
}
}
// This now counts login failures towards account lockout
// To enable password failures to trigger account lockout, I changed to shouldLockout: true
var result = await SignInManager.PasswordSignInAsync(model.Email, model.Password, model.RememberMe, shouldLockout: true);
switch (result)
{
case SignInStatus.Success:
return RedirectToLocal(returnUrl);
case SignInStatus.LockedOut:
return View("Lockout");
case SignInStatus.RequiresVerification:
return allowPassOnEmailVerfication ? RedirectToLocal(returnUrl) : RedirectToAction("SendCode", new { ReturnUrl = returnUrl, RememberMe = model.RememberMe });
case SignInStatus.Failure:
default:
ModelState.AddModelError("", "Invalid login attempt.");
return View(model);
}
}
Что это... ты по существу сделан! Тем не менее, меня всегда раздражает половина ответов, которые не проходят мимо потенциальных ловушек, которые вы нажмете позже, так что продолжайте наше приключение, не так ли?
3. Обновите управление/индекс
В нашем index.cshtml добавьте новый раздел для электронной почты. Прежде чем мы туда доберемся, отпустите добавьте поле, которое нам нужно в ManageViewmodel.cs
public class IndexViewModel
{
public bool HasPassword { get; set; }
public IList<UserLoginInfo> Logins { get; set; }
public string PhoneNumber { get; set; }
public bool TwoFactor { get; set; }
public bool BrowserRemembered { get; set; }
public string ConfirmedEmail { get; set; } //add this
public string UnConfirmedEmail { get; set; } //and this
}
Перейдите в действие индекса в нашем диспетчере управления, чтобы добавить это в нашу модель просмотра:
var userId = User.Identity.GetUserId();
var currentUser = await UserManager.FindByIdAsync(userId);
var unConfirmedEmail = "";
if (!String.IsNullOrWhiteSpace(currentUser.UnConfirmedEmail))
{
unConfirmedEmail = currentUser.UnConfirmedEmail;
}
var model = new IndexViewModel
{
HasPassword = HasPassword(),
PhoneNumber = await UserManager.GetPhoneNumberAsync(userId),
TwoFactor = await UserManager.GetTwoFactorEnabledAsync(userId),
Logins = await UserManager.GetLoginsAsync(userId),
BrowserRemembered = await AuthenticationManager.TwoFactorBrowserRememberedAsync(userId),
ConfirmedEmail = currentUser.Email,
UnConfirmedEmail = unConfirmedEmail
};
Наконец, для этого раздела мы можем обновить наш индекс, чтобы мы могли управлять этой новой электронной почтой:
<dt>Email:</dt>
<dd>
@Model.ConfirmedEmail
@if (!String.IsNullOrWhiteSpace(Model.UnConfirmedEmail))
{
<em> - Unconfirmed: @Model.UnConfirmedEmail </em> @Html.ActionLink("Cancel", "CancelUnconfirmedEmail",new {email=Model.ConfirmedEmail})
}
else
{
@Html.ActionLink("Change Email", "ChangeEmail")
}
</dd>
4. Добавьте эти новые изменения
Сначала добавьте ChangeEmail:
Просмотр модели:
public class ChangeEmailViewModel
{
public string ConfirmedEmail { get; set; }
[Required]
[EmailAddress]
[Display(Name = "Email")]
[DataType(DataType.EmailAddress)]
public string UnConfirmedEmail { get; set; }
}
Получить действие:
public ActionResult ChangeEmail()
{
var user = UserManager.FindById(User.Identity.GetUserId());
var model = new ChangeEmailViewModel()
{
ConfirmedEmail = user.Email
};
return View(model);
}
Вид:
@model ProjectName.Models.ChangeEmailViewModel
@{
ViewBag.Title = "Change Email";
}
<h2>@ViewBag.Title.</h2>
@using (Html.BeginForm("ChangeEmail", "Account", FormMethod.Post, new { @class = "form-horizontal", role = "form" }))
{
@Html.AntiForgeryToken()
<h4>New Email Address:</h4>
<hr />
@Html.ValidationSummary("", new { @class = "text-danger" })
@Html.HiddenFor(m=>m.ConfirmedEmail)
<div class="form-group">
@Html.LabelFor(m => m.UnConfirmedEmail, new { @class = "col-md-2 control-label" })
<div class="col-md-10">
@Html.TextBoxFor(m => m.UnConfirmedEmail, new { @class = "form-control" })
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" class="btn btn-default" value="Email Link" />
</div>
</div>
}
Действие HttpPost:
[HttpPost]
public async Task<ActionResult> ChangeEmail(ChangeEmailViewModel model)
{
if (!ModelState.IsValid)
{
return RedirectToAction("ChangeEmail", "Manage");
}
var user = await UserManager.FindByEmailAsync(model.ConfirmedEmail);
var userId = user.Id;
if (user != null)
{
//doing a quick swap so we can send the appropriate confirmation email
user.UnConfirmedEmail = user.Email;
user.Email = model.UnConfirmedEmail;
user.EmailConfirmed = false;
var result = await UserManager.UpdateAsync(user);
if (result.Succeeded)
{
string callbackUrl =
await SendEmailConfirmationTokenAsync(userId, "Confirm your new email");
var tempUnconfirmed = user.Email;
user.Email = user.UnConfirmedEmail;
user.UnConfirmedEmail = tempUnconfirmed;
result = await UserManager.UpdateAsync(user);
callbackUrl = await SendEmailConfirmationWarningAsync(userId, "You email has been updated to: "+user.UnConfirmedEmail);
}
}
return RedirectToAction("Index","Manage");
}
Теперь добавьте это предупреждение:
private async Task<string> SendEmailConfirmationWarningAsync(string userID, string subject)
{
string code = await UserManager.GenerateEmailConfirmationTokenAsync(userID);
var callbackUrl = Url.Action("ConfirmEmail", "Account",
new { userId = userID, code = code }, protocol: Request.Url.Scheme);
await UserManager.SendEmailAsync(userID, subject,
"Please confirm your account by clicking <a href=\"" + callbackUrl + "\">here</a>");
return callbackUrl;
}
И теперь, наконец, мы можем отменить новый адрес электронной почты:
public async Task<ActionResult> CancelUnconfirmedEmail(string emailOrUserId)
{
var user = await UserManager.FindByEmailAsync(emailOrUserId);
if (user == null)
{
user = await UserManager.FindByIdAsync(emailOrUserId);
if (user != null)
{
user.UnConfirmedEmail = "";
user.EmailConfirmed = true;
var result = await UserManager.UpdateAsync(user);
}
}
else
{
user.UnConfirmedEmail = "";
user.EmailConfirmed = true;
var result = await UserManager.UpdateAsync(user);
}
return RedirectToAction("Index", "Manage");
}
5. Обновить ConfirmEmail (самый последний шаг)
После всего этого назад и вперед мы можем подтвердить новое электронное письмо, что означает, что мы должны одновременно удалить старую электронную почту.
var result = UserManager.ConfirmEmail(userId, code);
if (result.Succeeded)
{
var user = UserManager.FindById(userId);
if (!string.IsNullOrWhiteSpace(user.UnConfirmedEmail))
{
user.Email = user.UnConfirmedEmail;
user.UserName = user.UnConfirmedEmail;
user.UnConfirmedEmail = "";
UserManager.Update(user);
}
}