【问题标题】:Identity 2 - Confirm Email and then allow user to set password身份 2 - 确认电子邮件,然后允许用户设置密码
【发布时间】:2016-09-15 15:39:47
【问题描述】:

我正在编写一个应用程序(MVC5、Identity 2.0 和 Entity Framework 6),它有一个只有管理员才能访问的用户部分。添加用户的唯一位置是此部分,除非您要注册一个新组织(它是用户的父级)。

我已经启动并运行了所有内容,但希望让用户的添加更加流畅。目前,管理员使用硬编码密码创建用户,并向他们发送一封电子邮件,要求他们确认他们的帐户。他们单击此按钮并确认帐户,然后他们必须登录。显然,硬编码密码不适合生产应用!

我真的很希望添加用户,生成随机密码,发送确认帐户电子邮件,然后一旦用户单击它,他们的帐户就被确认,然后他们被重定向到他们可以在其中重置自己的密码的页面。

那么,代码忍者,这可能吗?如果是这样,任何建议将不胜感激!

【问题讨论】:

    标签: asp.net-mvc asp.net-mvc-5 asp.net-identity


    【解决方案1】:

    是的。您可以删除管理员输入的硬编码密码,并将创建用户的调用替换为 var result = await UserManager.CreateAsync(user); 此时不提供密码。确保在创建时向用户发送一封邮件以确认电子邮件。这是example

    在confirmEmail 操作视图中,您可以创建密码设置表单并返回到confirmEmail。示例如下:

    HTTP 获取 ConfirmEmail

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

    您设置的密码表单中的 HTTP POST 到 ConfirmEmail:

        [HttpPost]
        [ValidateAntiForgeryToken]
        [AllowAnonymous]
        public async Task<ActionResult> ConfirmEmail(SetPasswordViewModel model, string userId, string code)
        {
            if (userId == null || code == null)
            {
                return View("Error");
            }
            if (!ModelState.IsValid)
            {
                return View(model);
            }
            var result = await UserManager.AddPasswordAsync(userId, model.NewPassword);
            if (result.Succeeded)
            {
                var user = await UserManager.FindByIdAsync(userId);
                if (user != null)
                {
                    await SignInManager.SignInAsync(user, isPersistent: false, rememberBrowser: false);
                }
                return await RedirectToDashboard(userId);
            }
    
            ViewBag.userId = userId;
            ViewBag.code = code;
    
            AddErrors(result);
            return View(model);
        }
    

    要放入 ConfirmEmailView 的示例表单

        @using (Html.BeginForm("ConfirmEmail", "Account", new { userId = ViewBag.userId, code = ViewBag.code }, FormMethod.Post, new { @class = "form-horizontal", role = "form" }))
                    {
                        @Html.AntiForgeryToken()
    
                        @Html.ValidationSummary("", new { @class = "color_orange" })
                          @Html.PasswordFor(m => m.NewPassword, new { @class = "form-control", placeholder = "New Password" })
                          @Html.PasswordFor(m => m.ConfirmPassword, new { @class = "form-control", placeholder = "Confirm Password" })
                          <input type="submit" value="Set password" class="btn" />
    
    
                    }
    

    记得给你的confirmEmail视图添加一个模型@model [ProjectName].Models.SetPasswordViewModel

    并创建 SetPasswordViewModel:

        public class SetPasswordViewModel
    {
        [Required]
        [StringLength(100, ErrorMessage = "The {0} must be at least {2} characters long.", MinimumLength = 6)]
        [DataType(DataType.Password)]
        [Display(Name = "New password")]
        public string NewPassword { get; set; }
    
        [DataType(DataType.Password)]
        [Display(Name = "Confirm new password")]
        [Compare("NewPassword", ErrorMessage = "The new password and confirmation password do not match.")]
        public string ConfirmPassword { get; set; }
    }
    

    【讨论】:

    • 超级有用且详细!
    【解决方案2】:

    我也需要相同的功能。我通过脏代码实现了这一点。

    [AllowAnonymous]
    Public ActionResult ConfirmEmail(string userId, string code)
    {
       if(userId == null || code == null)
       {
          return View("Error");  
       }
       var user = UserManager.FindById(userId);
       if(user == null)
       {
    
       }
       else
       { 
          RunAsync(ForceResetPassword(user));
          return RedirectToAction("ResetPasswordAfterConfirmation","Account");
       }
    }
    
    
    Public async Task<ActionResult> ForceResetPassword(ApplicationUser user)
    {
     string code = await UserManager.GeneratePasswordResetTokenAsync(user.Id);
    
     var callbackUrl = Url.Action("Reset Password", "Account", new {userId = user.Id, code = code}, protocol: Request.Url.Scheme); 
    await UserManager.SendEmailAsync(user.Id,"Reset Password","Please reset your password by clicking <a href=\"" + callbackUrl + "\">here</a>");
    
    //Insert send email code here
        }
    
    private void RunAsync(Task task)
    {
       task.ContinueWith(t =>
       {
       }, TaskContinuationOptions.OnlyOnFaulted);
    }
    

    因此,他们将在管理员创建帐户后收到确认电子邮件,然后在单击链接后,他们将再次收到另一封电子邮件以重置密码。

    如果您有更好的方法来实现这一点,我也很高兴知道。 :)

    【讨论】:

      猜你喜欢
      • 2017-02-22
      • 1970-01-01
      • 2014-10-20
      • 2017-04-30
      • 2016-08-11
      • 1970-01-01
      • 2023-03-29
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多