2014-08-29 97 views
31

有誰知道如何讓用戶使用電子郵件確認更改ASP.NET身份的用戶名/電子郵件?有很多關於如何更改密碼的示例,但我無法找到任何關於此的信息。.NET身份電子郵件/用戶名更改

回答

41

更新2017年12月一些很好的意見已提出在評論:

  • 最好有一個獨立的領域有新郵件,而它得到證實 - 在情況下,當用戶輸入了不正確的電子郵件。等到新電子郵件確認後,再將其作爲主電子郵件。請看下面Chris_的非常詳細的答案。
  • 也有可能是一個情況下帳戶與電子郵件已經存在 - 請確保您檢查過,否則就不可能有麻煩。

這是一個非常基本的解決方案,沒有涵蓋所有可能的組合,因此請使用您的判斷並確保您通讀評論 - 這裏已經提出了非常好的觀點。

// get user object from the storage 
var user = await userManager.FindByIdAsync(userId); 

// change username and email 
user.Username = "NewUsername"; 
user.Email = "[email protected]"; 

// 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"); 
} 
+0

感謝,今天不能嘗試,但會讓你知道 – devlock 2014-09-01 12:06:30

+0

高興你加入URL編碼爲股票微軟ASPNET身份樣本被打破,並沒有這樣做。 – jakejgordon 2014-10-14 16:56:57

+3

我建議你也註銷用戶,以便他們不能通過基於cookie的身份驗證繼續,直到他們重新確認他們的電子郵件:http://stackoverflow.com/questions/25878218/asp-net-identity-2-0 -sign-out-another-user – BenjiFB 2014-12-10 16:00:46

31

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.更新您的登錄

現在,我們需要確保我們的登錄是檢查舊的電子郵件確認以及使物可以是「在地獄」,而我們等待用戶確認這個新的電子郵件:

​​

就是這樣。你基本上完成了!然而,我總是會因爲一半的答案而感到惱火,這些答案並沒有讓你走過你後來會遇到的潛在陷阱,所以讓我們繼續我們的冒險吧?

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); 
    } 
} 
+4

我們可以添加索賠而不是添加額外的字段 – gldraphael 2015-12-22 04:12:19

+2

這是一個很好的完整答案,應該是真正的答案。感謝發佈這是非常有幫助的。 – 2016-01-28 11:09:04

+1

謝謝@RichardMcKenna,很高興你發現它有幫助。我總是試圖保持簡短......但是想要給出儘可能多的細節。 – 2016-01-28 18:32:34

相關問題