2016-01-30 30 views
0

我已經使用ASP.NET MVC構建了一個Web應用程序。我原來並沒有啓用「忘記密碼」位。我現在有大約3個人使用該服務,並且我預計在本月內部署了真正的電子郵件確認和忘記密碼功能。我希望我的當前用戶(包括我)能夠訪問忘記的密碼功能,但我似乎無法找到一種方法,當EmailConfirmed對我們所有人都是虛假的。 EmailConfirmed必須是真實的,然後纔會發送忘記的密碼電子郵件。設置ASP.NET允許現有用戶使用新的密碼重置功能

目標:允許當前用戶使用重置密碼功能

問題:現有用戶還沒有證實他們的電子郵件,因此他們沒有資格申請密碼重置。

可能的解決方案:

  1. 數據庫中的每個現有用戶的EmailConfirmed列手動更改爲True。
  2. 刪除現有的用戶,並使用電子郵件確認重新註冊。

有誰知道如何做到這一點?我在尋找正確的解決方案嗎?最後,我應該注意到我在IIS上使用LocalDB,所以我沒有直接訪問來編輯表。我確實擁有.mdf文件,但似乎直接進行編輯可能比我假設存在的其他可能的解決方案更難。我將非常感謝您的幫助!

謝謝!

回答

1

因爲我只用了三個用戶,我結束了從

C刪除文件:\的Inetpub \ wwwroot的\應用程序名稱\程序App_Data

有一個.MDF文件和.LDF文件。這些是用於LocalDB的文件。我失去了所有現有的用戶註冊,但是當(3)用戶重新註冊時,他們被提示輸入確認郵件(這是我想要的)。對於早期階段的計劃來說,這是一個可行的解決方案,但對於這個問題來說,這是一個可怕的解決方案。我結束了破壞.mdf文件,這是我甚至嘗試刪除/重新生成它的唯一原因。這裏僅供參考,但不要試圖將其作爲解決您的網站問題的解決方案,除非您是唯一的用戶!仍在尋找更好的選擇,以供將來參考!謝謝!

0

沒有第二種形式的身份驗證(例如確認的電子郵件地址,電話號碼,安全問題,PIN等)的用戶不能信任密碼重置。

如果您再次遇到這個問題,我認爲最好的解決方案是在用戶登錄後提醒用戶他們沒有經過確認的電子郵件,並且他們可能會失去對其帳戶的訪問權限不及時確認電子郵件。這仍然會讓一些固執的用戶不幸運,他們拒絕確認電子郵件並丟失密碼,但在這種情況下,您可以根據具體情況使用較小的用戶羣。

要完成上述建議的解決方案,您可以從登錄後立即提醒用戶注意缺少電子郵件,其中包括在Account控制器中創建重定向。以下是Visual Studio在創建新的ASP.NET 4.5.2 MVC Web應用程序時生成的股票登錄方法的修改版本。請特別注意SignInStatus.Success的情況,它會重定向到我創建的名爲RequestEmailConfirmation的新控制器操作。

控制器/ AccountController.cs:

// POST: /Account/Login 
[HttpPost] 
[AllowAnonymous] 
[ValidateAntiForgeryToken] 
public async Task<ActionResult> Login(LoginViewModel model, string returnUrl) 
{ 
    if (!ModelState.IsValid) 
    { 
     return View(model); 
    } 

    // This doesn't count login failures towards account lockout 
    // To enable password failures to trigger account lockout, change to shouldLockout: true 
    var result = await SignInManager.PasswordSignInAsync(model.Email, model.Password, model.RememberMe, shouldLockout: false); 
    switch (result) 
    { 
     case SignInStatus.Success: 
      // Redirect user to confirm an email address. 
      if (!(await UserManager.IsEmailConfirmedAsync(User.Identity.GetUserId()))) 
      { 
       return RedirectToAction("RequestEmailConfirmation", "Account"); 
      } 
      else 
      { 
       return RedirectToLocal(returnUrl); 
      } 
     case SignInStatus.LockedOut: 
      return View("Lockout"); 
     case SignInStatus.RequiresVerification: 
      return RedirectToAction("SendCode", new { ReturnUrl = returnUrl, RememberMe = model.RememberMe }); 
     case SignInStatus.Failure: 
     default: 
      ModelState.AddModelError("", "Invalid login attempt."); 
      return View(model); 
    } 
} 

// GET: /Account/RequestEmailConfirmation 
public ActionResult RequestEmailConfirmation() 
{ 
    return View(); 
} 

此修改登錄操作將忽略任何returnUrl用戶可能有。如果需要,可以維護該信息,但對於此示例,如果用戶被重定向以確認電子郵件,則會丟失該信息。

接下來,我們看一個新的視圖頁面和一個視圖模型,以配合RequestEmailConfirmation操作。該視圖爲用戶提供了一個簡單的表單,用於鍵入並重新鍵入他們的電子郵件,並且視圖模型存儲該信息以傳遞給我們稍後將看到的另一個控制器操作。請注意,此時用戶已登錄並可選擇忽略電子郵件確認請求,而不是導航到網站上的其他密碼保護內容。

查看/帳號/ RequestEmailConfirmation.cshtml

@using MyWebApplication.Models 
@model RequestEmailConfirmationViewModel 
@{ 
    ViewBag.Title = "Request Email Confirmation"; 
} 

<h2>@ViewBag.Title.</h2> 
<div class="row"> 
    <div class="col-md-8"> 
     <section id="loginForm"> 
      @using (Html.BeginForm("RequestEmailConfirmation", "Account", FormMethod.Post, new { @class = "form-horizontal", role = "form" })) 
      { 
       @Html.AntiForgeryToken() 
       <h4>Confirm Email Address</h4> 
       <span class="text-danger">You have not yet confirmed an email address for this account. Please confirm your email address below to ensure access to your account in the event of a lost or forgotten password.</span> 
       <hr /> 
       @Html.ValidationSummary(true, "", new { @class = "text-danger" }) 
       <div class="form-group"> 
        @Html.LabelFor(m => m.Email, new { @class = "col-md-2 control-label" }) 
        <div class="col-md-10"> 
         @Html.TextBoxFor(m => m.Email, new { @class = "form-control" }) 
         @Html.ValidationMessageFor(m => m.Email, "", new { @class = "text-danger" }) 
        </div> 
       </div> 
       <div class="form-group"> 
        @Html.LabelFor(m => m.ConfirmEmail, new { @class = "col-md-2 control-label" }) 
        <div class="col-md-10"> 
         @Html.TextBoxFor(m => m.ConfirmEmail, new { @class = "form-control" }) 
         @Html.ValidationMessageFor(m => m.ConfirmEmail, "", new { @class = "text-danger" }) 
        </div> 
       </div> 
       <div class="form-group"> 
        <div class="col-md-offset-2 col-md-10"> 
         <input type="submit" value="Confirm" class="btn btn-default" /> 
        </div> 
       </div> 
      } 
     </section> 
    </div> 
</div> 

@section Scripts { 
    @Scripts.Render("~/bundles/jqueryval") 
} 

型號/ RequestEmailConfirmationViewModel.cshtml:

using System.ComponentModel.DataAnnotations; 

namespace MyWebApplication.Models 
{ 
    public class RequestEmailConfirmationViewModel 
    { 
     [Required] 
     [StringLength(100, ErrorMessage = "The {0} must be at least {2} characters long.", MinimumLength = 6)] 
     [DataType(DataType.EmailAddress)] 
     [Display(Name = "Email")] 
     public string Email { get; set; } 

     [DataType(DataType.EmailAddress)] 
     [Display(Name = "Confirm Email")] 
     [Compare("Email", ErrorMessage = "The email and confirmation email do not match.")] 
     public string ConfirmEmail { get; set; } 
    } 
} 

有了電子郵件確認申請表,我們繼續在三個控制器動作Account控制器處理表單提交,「感謝您提交確認電子郵件」頁面,以及當用戶訪問確認電子郵件中提供的鏈接時處理確認電子郵件的操作。這裏的重要部分是電子郵件確認令牌生成以及該令牌收據的後續確認,這可以讓我們安全地設置用戶數據庫中的EmailConfirmed值。下面還創建了兩個新視圖,第一個顯示「謝謝您提交確認電子郵件」消息,第二個顯示「謝謝您確認您的電子郵件」消息。

控制器/ AccountController.cs(續):

// POST: /Account/Register 
[HttpPost] 
[ValidateAntiForgeryToken] 
public async Task<ActionResult> RequestEmailConfirmation(RequestEmailConfirmationViewModel model) 
{ 
    if (ModelState.IsValid) 
    { 
     // Send an email confirmation. 
     string userId = User.Identity.GetUserId(); 
     string code = await UserManager.GenerateEmailConfirmationTokenAsync(userId); 
     var callbackUrl = Url.Action("ConfirmEmail", "Account", new { userId = userId, code = code }, protocol: Request.Url.Scheme); 
     await UserManager.SendEmailAsync(user.Id, "Confirm Email Address", "Please confirm your email address by clicking <a href=\"" + callbackUrl + "\">here</a>."); 

     return RedirectToAction("RequestEmailConfirmationSubmitted", "Home"); 
    } 

    // If we got this far, something failed, redisplay form 
    return View(model); 
} 

// GET: /Account/RequestEmailConfirmationSubmitted 
[AllowAnonymous] 
public ActionResult RequestEmailConfirmationSubmitted() 
{ 
    return View(); 
} 

// GET: /Account/ConfirmEmail 
[AllowAnonymous] 
public async Task<ActionResult> ConfirmEmail(string userId, string code) 
{ 
    if (userId == null || code == null) 
    { 
     return View("Error"); 
    } 
    var result = await UserManager.ConfirmEmailAsync(userId, code); 
    return View(result.Succeeded ? "ConfirmEmail" : "Error"); 
} 

查看/帳號/ RequestEmailConfirmationSubmitted.cshtml

@{ 
    ViewBag.Title = "Email Address Submitted"; 
} 

<h2>@ViewBag.Title.</h2> 
<div> 
    <p> 
     Thank you for submitting your email address. An email with a confirmation link will be sent to you shortly to verify your ownership. 
    </p> 
</div> 

查看/帳號/ ConfirmEmail.cshtml:

@{ 
    ViewBag.Title = "Email Address Confirmed"; 
} 

<h2>@ViewBag.Title.</h2> 
<div> 
    <p> 
     Thank you for confirming your email. 
    </p> 
</div> 

通過上面的代碼,我假設您已經設置了一個電子郵件服務來實際發送確認電子郵件給用戶。一旦用戶確認了他們的電子郵件,他們將能夠安全地使用密碼重置功能。雖然我沒有完全測試過這些代碼,但是這應該爲您提供解決問題的充分方法。

+0

這聽起來像是一個很好的解決方案,但我在詢問有關如何實現它的信息。我明白爲什麼密碼重置僅限於已確認的電子郵件,並且我明白,您的建議是解決方案的一種好方法。請隨時添加一些關於如何去做的有用的技術信息。 – trademark

+0

@trademark完成。 – Chase