dev*_*ock 48 asp.net asp.net-identity
有谁知道如何让用户通过电子邮件确认更改带有ASP.NET身份的用户名/电子邮件?有很多关于如何更改密码的例子,但我找不到任何关于此的信息.
tra*_*max 48
2017年12月更新评论中提出了一些好处:
这是一个非常基本的解决方案,并未涵盖所有可能的组合,因此请使用您的判断并确保您阅读评论 - 在那里提出了非常好的观点.
// get user object from the storage
var user = await userManager.FindByIdAsync(userId);
// change username and email
user.Username = "NewUsername";
user.Email = "New@email.com";
// Persiste the changes
await userManager.UpdateAsync(user);
// generage email confirmation code
var emailConfirmationCode = await userManager.GenerateEmailConfirmationTokenAsync(user.Id);
// generate url for page where you can confirm the email
var callbackurl= "http://example.com/ConfirmEmail";
// append userId and confirmation code as parameters to the url
callbackurl += String.Format("?userId={0}&code={1}", user.Id, HttpUtility.UrlEncode(emailConfirmationCode));
var htmlContent = String.Format(
@"Thank you for updating your email. Please confirm the email by clicking this link:
<br><a href='{0}'>Confirm new email</a>",
callbackurl);
// send email to the user with the confirmation link
await userManager.SendEmailAsync(user.Id, subject: "Email confirmation", body: htmlContent);
// then this is the action to confirm the email on the user
// link in the email should be pointing here
public async Task<ActionResult> ConfirmEmail(string userId, string code)
{
var confirmResult = await userManager.ConfirmEmailAsync(userId, code);
return RedirectToAction("Index");
}
Run Code Online (Sandbox Code Playgroud)
Chr*_*is_ 38
Trailmax得到了大部分权利,但正如评论所指出的那样,如果用户在更新时弄乱他们的新电子邮件地址,他们将基本上陷入困境.
要解决此问题,必须向用户类添加其他属性并修改登录.(注意:这个答案将通过MVC 5项目解决)
这是我拍摄的地方:
1.修改用户对象 首先,让我们更新应用程序用户以添加我们需要的其他字段.您将在Models文件夹的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
}
Run Code Online (Sandbox Code Playgroud)
如果您想要查看更深入的示例,请查看此处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;
Run Code Online (Sandbox Code Playgroud)
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);
}
}
Run Code Online (Sandbox Code Playgroud)
就是这样......你基本上完成了!但是,我总是对半个答案感到恼火,这些答案不会让你过去后来会遇到的潜在陷阱,所以让我们继续我们的冒险,好吗?
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
}
Run Code Online (Sandbox Code Playgroud)
跳转到我们的管理控制器中的索引操作,将其添加到我们的viewmodel:
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
};
Run Code Online (Sandbox Code Playgroud)
最后,对于本节,我们可以更新索引以允许我们管理这个新的电子邮件选项:
<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>
Run Code Online (Sandbox Code Playgroud)
4.添加这些新修改
首先,让我们添加ChangeEmail:
查看型号:
public class ChangeEmailViewModel
{
public string ConfirmedEmail { get; set; }
[Required]
[EmailAddress]
[Display(Name = "Email")]
[DataType(DataType.EmailAddress)]
public string UnConfirmedEmail { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
行动:
public ActionResult ChangeEmail()
{
var user = UserManager.FindById(User.Identity.GetUserId());
var model = new ChangeEmailViewModel()
{
ConfirmedEmail = user.Email
};
return View(model);
}
Run Code Online (Sandbox Code Playgroud)
视图:
@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>
}
Run Code Online (Sandbox Code Playgroud)
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");
}
Run Code Online (Sandbox Code Playgroud)
现在添加该警告:
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;
}
Run Code Online (Sandbox Code Playgroud)
现在终于,我们可以取消新的电子邮件地址:
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");
}
Run Code Online (Sandbox Code Playgroud)
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);
}
}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
33426 次 |
最近记录: |