【问题标题】:MVC Admin reset of User Password用户密码的 MVC 管理员重置
【发布时间】:2018-10-19 16:24:40
【问题描述】:

经过一番折腾,在ADyson 的出色帮助下,我完成了这项工作。

在我的系统上,当管理员用户登录时,会出现一个链接,让他们进入用户管理系统。这提供了一个用户列表,可以创建另一个用户、删除他们或更改他们的详细信息。

此外,当任何用户登录时,他们都可以更改自己的密码。但是,如果用户忘记了密码,管理员用户必须重置密码。我不会通过电子邮件向他们发送链接或任何花哨的东西。在管理屏幕的“列出用户”位中,有一个操作列,其中包含编辑、删除、显示详细信息和重置密码的链接。

我有一个 ApplicationUsersController,其中包含编辑、删除等功能。我有一系列 ApplicationUsers 视图,称为 Create、Edit、Delete、Details、Edit、Index。大部分代码是在我创建 ApplicationUsersController 并选择创建视图时生成的。还有一个 ResetUserPasswordsViewModel 。这是 ResetPassword 视图:

@model ICWeb.Models.ResetUserPasswordViewModel

@{
    ViewBag.Title = "Reset User Password";
    Layout = "~/Views/Shared/_Layout.cshtml";
}

<h2>@ViewBag.Title</h2>


@using (Html.BeginForm())
{
    @Html.AntiForgeryToken()

    <div class="form-horizontal">
        <hr />
        @Html.ValidationSummary(true, "Please fix the errors displayed", new { @class = "text-danger" })
        @Html.HiddenFor(model => model.Id)

        <div class="form-group">
            @Html.LabelFor(model => model.NewPassword, htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.NewPassword, new { htmlAttributes = new { @class = "form-control", @autofocus = "autofocus" } })
                @Html.ValidationMessageFor(model => model.NewPassword, "", new { @class = "text-danger" })
            </div>
        </div>

        <div class="form-group">
            @Html.LabelFor(model => model.ConfirmPassword, htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.ConfirmPassword, new { htmlAttributes = new { @class = "form-control" } })
                @Html.ValidationMessageFor(model => model.ConfirmPassword, "", new { @class = "text-danger" })
            </div>
        </div>

        <div class="form-group">
            <div class="col-md-offset-2 col-md-10">
                <input type="submit" value="Reset Password" class="btn btn-default" />
            </div>
        </div>
    </div>
}
<div>
    @Html.ActionLink("Back to List", "Index")
</div>

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

在我的控制器中:

    // GET: /ApplicationUsers/ResetPassword
    public ActionResult ResetPassword(string id)
    {
        return View(new ResetUserPasswordViewModel() { Id = id });
    }

    //POST: /ApplicationUsers/ResetPassword
    [HttpPost]
    [ValidateAntiForgeryToken]
    public async Task<ActionResult> ResetPassword(ResetUserPasswordViewModel model)
    {
        if (!ModelState.IsValid)
        {
            return View(model);
        }

        ApplicationDbContext context = new ApplicationDbContext();
        UserStore<ApplicationUser> store = new UserStore<ApplicationUser>(context);
        UserManager<ApplicationUser> UserManager = new UserManager<ApplicationUser>(store);
        string userId = model.Id;
        string newPassword = model.NewPassword;
        string hashedNewPassword = UserManager.PasswordHasher.HashPassword(newPassword);
        ApplicationUser cUser = await store.FindByIdAsync(userId);
        await store.SetPasswordHashAsync(cUser, hashedNewPassword);
        await store.UpdateAsync(cUser);

        return RedirectToAction("Index");
    }

经过一番折腾,我重新做了这个功能。视图现在加载,我可以输入 2 个新密码。当我提交时,ResetPassword 函数运行。当我单步执行代码时,我可以看到它具有我输入的密码,并且通过编辑 GET 函数以使用 Id 填充模型,我现在获得了用户的 Id。整个控制器的访问权限仅限于具有管理员权限的用户,因此除非您是管理员,否则您无法在此处执行任何操作。

在我的 ResetUserPasswordModel 我有:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.ComponentModel.DataAnnotations;

namespace ICWeb.Models
{
    public class ResetUserPasswordViewModel
    {
        public string Id { get; set; }

        [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; }
    }
}

所有内容都已排序,非常感谢您的帮助。

【问题讨论】:

  • 也许您需要一个视图模型对象,那么哪个 确实 包含这些字段?另外,为什么您将id 作为单独的参数?确定这已经是模型的一部分了吗?
  • id 可能是我正在尝试的东西的宿醉。我已将其删除。我添加了一个 ResetUserPasswordViewModel 类。它包含一个 Id 属性、密码和一个确认密码属性
  • 好的。那么……它解决了你的问题吗?
  • 没有。我将视图更改为在包含 id、newpassword 和 confirmpassword 属性的开头行中使用 ApplicationUsersModels。 httppost 函数 ResetPassword 显然是错误的。有什么想法吗?我要做的就是为 AspNetUsers 中的选定用户重置密码。用户管理页面列出了我的用户,重置密码链接的格式为:ApplicationUsers/ResetPassword/d1b8e05e-07df-4276-95e6-959b6c6a2b99 因此,ID 被传递到重置密码页面。
  • 帖子也需要接受您的新视图模型作为参数。是你做的吗?也许用最新的代码和当前的问题更新您的问题。仅根据描述很难确定

标签: asp.net-mvc


【解决方案1】:

在我正在开发的系统中(但尚未完成或测试)我已经写了这个。它有效,所以应该是一个很好的起点。请注意,视图模型会处理不匹配的密码,因此已经为您介绍了这一点。

我对用户管理器使用直接注入 - 只需将我的 _userManager 替换为您自己的实例即可。

@model Models.ResetPasswordViewModel
@{
    ViewBag.Title = "Reset password";
}

<div class="container">
    @if (ViewBag.Error != null)
    {
        <div class="alert-danger mb-2">Error(s) occured : @ViewBag.Error</div>
        @Html.ActionLink("Back to List", "AllUsers", null, new { @class = "btn btn-outline-primary" })
    }
    else
    {
        using (Html.BeginForm("ResetPassword", "Account", FormMethod.Post, new { @class = "form-horizontal", role = "form" }))
        {
            @Html.AntiForgeryToken()

            @Html.ValidationSummary("", new { @class = "text-danger" })

            @Html.HiddenFor(x => x.Id)

            <div class="form-group">
                @Html.LabelFor(model => model.UserName, htmlAttributes: new { @class = "control-label" })
                @Html.EditorFor(model => model.UserName, new { htmlAttributes = new { @class = "form-control", @readonly = "" } })
            </div>

            <div class="form-group">
                @Html.LabelFor(m => m.Password, new { @class = "control-label" })
                @Html.PasswordFor(m => m.Password, new { @class = "form-control" })
            </div>
            <div class="form-group">
                @Html.LabelFor(m => m.ConfirmPassword, new { @class = "control-label" })
                @Html.PasswordFor(m => m.ConfirmPassword, new { @class = "form-control" })
            </div>

            <div class="form-group d-flex">
                @Html.ActionLink("Back to User Edit", "EditUser", "Account", new { userId = Model.Id }, new { @class = "btn btn-outline-primary" })

                <input type="submit" value="Reset Password" class="btn btn-primary ml-auto" />
            </div>
        }
    }
</div>


  public class ResetPasswordViewModel
    {
        [Display(Name = "User Id")]
        public string Id { get; set; }

        [Display(Name = "User Name")]
        public string UserName { get; set; }

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

        [DataType(DataType.Password)]
        [Display(Name = "Confirm password")]
        [Compare("Password", ErrorMessage = "The password and confirmation password do not match.")]
        public string ConfirmPassword { get; set; }
    }


[ValidateAntiForgeryToken]
public async Task<ActionResult> ResetPassword(ResetPasswordViewModel model)
{
    if (!ModelState.IsValid)
    {
        return View(model);
    }

    var user = _userManager.FindById(model.Id);

    IdentityResult result = null;

    if (user != null)
    {
        string code = await _userManager.GeneratePasswordResetTokenAsync(user.Id);

        result = await _userManager.ResetPasswordAsync(user.Id, code, model.Password);

        if (result.Succeeded)
        {
            return RedirectToAction("ResetPasswordConfirmation", "Account", model);
        }
    }

    // return errors
    var s = new System.Text.StringBuilder();
    //
    foreach (var e in result.Errors)
    {
        if (s.Length > 0)
        {
            s.Append(", ");
        }

        s.Append(e);
    }

    ViewBag.Error = s.ToString();

    return View();
}

【讨论】:

  • 因为我是新手,我不确定我是否理解你所做的。在视图中,我看到您有 x、m 和模型。你是怎么拿到3的?这是陡峭的学习曲线 :) 我在网上做一个 MVC 课程,但你不能真正问它问题,所以你先四处寻找,尝试一下。如果你不能更进一步,我会来这里问。
  • HiddenFor、EditorFor(等等)括号中的代码假定您正在引用模型,因此您将它们命名为什么并不重要(尝试在设计器中将鼠标悬停在它们上方,然后您就可以)会看到它指向模型。因此,a=>a.SomeField 和 b=>b.SomeField 创建相同的东西,一个具有相同结果的 Lambda 表达式。
猜你喜欢
  • 2012-09-27
  • 1970-01-01
  • 2014-11-04
  • 2014-09-28
  • 2012-06-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多