【问题标题】:Token is null causing invalid ModelState令牌为 null 导致无效的 ModelState
【发布时间】:2018-02-02 17:16:33
【问题描述】:

我有一个模型允许用户重置密码:

public class PasswordResetViewModel
{
    [Required]
    [EmailAddress(ErrorMessage = "Please ensure requestor email is valid")]
    [UIHint("email")]
    public string Email { get; set; }
    [Required]
    [DataType(DataType.Password)]
    public string Password { get; set; }
    [Required]
    [DataType(DataType.Password), Compare("Password")]
    public string ConfirmPassword { get; set; }
    [Required]
    public string Token { get; set; }
}

token是通过下面的action方法设置的:

[AllowAnonymous]
        public async Task<IActionResult> PasswordResetEmail(UserEmailViewModel model)
        {
            if (ModelState.IsValid)
            {
                AppUser user = await userManager.FindByEmailAsync(model.Email);
                if (user == null)
                {
                    // Don't reveal that the user does not exist or is not confirmed
                    TempData["message"] = null;
                    return View("Login"); 
                }

                var token = userManager.GeneratePasswordResetTokenAsync(user).Result;
                var resetLink = Url.Action("PasswordReset", "Account", new { token = token }, protocol: HttpContext.Request.Scheme);
                var message = "<a href=\"" + resetLink + "\">Click here to reset your password</a>";
                string subjectLine = "Reset your password";
                //send email with email service
                emailService.SendHtmlEmail(message, user.Email, subjectLine);

                TempData["message"] = $"Check email for password reset link";
                return View("Login");
            }

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

电子邮件重定向到以下视图:

@model PasswordResetViewModel
@{
    ViewBag.Title = "Reset Password";
    Layout = "_Layout";
}

<div class="bg-primary panel-body"><h4>ViewBag.Title</h4></div>
<div class="text-danger" asp-validation-summary="All"></div>
<form asp-controller="Account" asp-action="PasswordReset" method="post">
    <input type="hidden" asp-for="Token" />
    <div class="form-group">
        <label asp-for="Email"></label>
        <input asp-for="Email" class="form-control" />
    </div>
    <div class="form-group">
        <label asp-for="Password"></label>
        <input asp-for="Password" class="form-control" />
    </div>
    <div class="form-group">
        <label asp-for="ConfirmPassword"></label>
        <input asp-for="ConfirmPassword" class="form-control" />
    </div>
    <button class="btn btn-primary btn-space" type="submit">Reset Password</button>
</form>

但是,提交后,以下操作项中的令牌为空白,导致 ModelState 无效

[HttpPost]
        [AllowAnonymous]
        public async Task<IActionResult> PasswordReset(PasswordResetViewModel obj)
        {
            if (ModelState.IsValid)
            {
                AppUser user = await userManager.FindByEmailAsync(obj.Email);
                if (user != null)
                {
                    IdentityResult result = await userManager.ResetPasswordAsync(user, obj.Token, obj.Password);

                    if (result.Succeeded)
                    {
                        TempData["message"] = $"Password reset successful!";
                        return View("Login");
                    }
                    else
                    {
                        AddErrorsFromResult(result);
                        TempData["message"] = $"Error while resetting the password. Password was not reset. Send another reset password and try again";
                        return View("ForgotPassword");
                    }
                }
            else //user email not found in database
            {
                TempData["message"] = $"Error while resetting the password. Password was not reset. Send another reset password and try again";
                return View("ForgotPassword");
            }
        }

电子邮件链接有效,并且似乎具有有效令牌。但是,此令牌值不会在 PasswordReset 操作方法中从 View 传递到控制器。

下面是渲染的 HTML

<div class="bg-primary panel-body"><h4>ViewBag.Title</h4></div>
<div class="text-danger validation-summary-valid" data-valmsg-summary="true"><ul><li style="display:none"></li>
</ul></div>
<form method="post" action="/Account/PasswordReset">
    <input type="hidden" data-val="true" data-val-required="The Token field is required." id="Token" name="Token" value="" />
    <div class="form-group">
        <label for="Email">Email</label>
        <input class="form-control" type="email" data-val="true" data-val-email="Please ensure requestor email is valid" data-val-required="The Email field is required." id="Email" name="Email" value="" />
    </div>
    <div class="form-group">
        <label for="Password">Password</label>
        <input class="form-control" type="password" data-val="true" data-val-required="The Password field is required." id="Password" name="Password" />
    </div>
    <div class="form-group">
        <label for="ConfirmPassword">ConfirmPassword</label>
        <input class="form-control" type="password" data-val="true" data-val-equalto="&#x27;ConfirmPassword&#x27; and &#x27;Password&#x27; do not match." data-val-equalto-other="*.Password" data-val-required="The ConfirmPassword field is required." id="ConfirmPassword" name="ConfirmPassword" />
    </div>
    <button class="btn btn-primary btn-space" type="submit">Reset Password</button>
<input name="__RequestVerificationToken" type="hidden" value="CfDJ8P701H9_W2VHikt7vFU7qE_hDXNPQe-vU2zRITMm_SakSlqmLU7lTfycwmVg4bPhvqWHdv7d3n4YbJYOMqCVK55Rn0KqQCoZplL9a_eZDF48oiQExiaSTn4BcXdfhzWqjc1oQgyUQTyCbt1Zu1zhrva5dWPXXhXtxF442_Zn11GL8zBiqEsscAt2VbpcmkjJ8g" /></form>

我尝试将行更改为

var resetLink = Url.Action("PasswordReset", "Account", new { Token = token }, protocol: HttpContext.Request.Scheme);

如果Token 参数区分大小写但它没有修复它。

【问题讨论】:

  • 令牌实际上是如何到达视图的?它是否出现在查看源代码中?
  • 请将呈现的 HTML 也添加到您的问题中。
  • @RAM 查看编辑。 Token 值为 null,但 __RequestVerificationToken 具有正确的值。我以前用过类似的方法,没有这个问题
  • @SLaks 我是 .NET Core 的新手,但我认为它是通过 asp-for="Token"
  • 但是Token 是从哪里来的?该视图是如何呈现的?

标签: c# asp.net-core token


【解决方案1】:

您应该有一个带有token 参数的Get Action 方法!像下面的代码一样,在Get方法中填写ViewModelToken属性,然后传递给View,否则为空:

[HttpGet]
[AllowAnonymous]
public async Task<IActionResult> PasswordReset(string token)
{
        //Other codes

    var vm = new PasswordResetViewModel();
    vm.Token = token;


    return View("ForgotPassword", vm);
}

现在手动调用ResetPassword 链接(eq:http://localhost:PORT/Account/ResetPassword?token=123456)并查看呈现的HTML。 Token 字段的隐藏输入应该有这个值:123456

【讨论】:

  • 谢谢。我错误地使用了public ViewResult PasswordReset() =&gt; View() 而没有传递字符串令牌
猜你喜欢
  • 2020-03-09
  • 2019-04-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-07-17
  • 1970-01-01
  • 2013-11-20
  • 2019-07-16
相关资源
最近更新 更多